LINUX.ORG.RU

Шаблоны вместо виртуального наследования

 ,


1

3

Есть у меня C++ные интерфейсы IReadableDataset и его наследники: IEditableDataset и IStatistics. Наследование IReadableDataset у них у обоих виртуальное.

И есть реализация Dataset, которая наследует IEditableDataset и IStatistics. А значит, виртуально наследует IReadableDataset через IStatistics и IEditableDataset.

Имею спросить: нельзя ли здесь отказаться от виртуального наследования? Вроде есть какой-то способ эмулировать его с помощью шаблонов?


Если они у тебя I*, то «интерфейсы»(не имеют состояния)? Тогда не нужно виртуальное наследование, делай обычное...

anonymous ()
Ответ на: комментарий от anonymous

Он их через вышележащие интерфейсы наследует, не напрямую.

Поправил пост.

Yak ()
Ответ на: комментарий от anonymous

Там меня замучают ambiguious access'ом, если я не сделаю наследование виртуальным. А каждый раз указывать IReadableDataset::MegaMethod вместо MegaMethod как-то неохота.

Yak ()

Имею спросить: нельзя ли здесь отказаться от виртуального наследования?

как-то так:

class Dataset : public IEditableDataset<IStatistics>
class IStatistics : public IReadableDataset

template <typename T=IReadableDataset>
class IEditableDataset : public T
wota ★★ ()
Ответ на: комментарий от Yak
// Общий для всех интерфейс
class IReadableDataset {};

// Первый из двух родителей для Dataset1
template <typename T=IReadableDataset>
class IEditableDataset : public T {};

// Второй из двух родителей для Dataset1
class IStatistics : public IReadableDataset {};

// Наследует IReadableDataset, IEditableDataset, IStatistics
class Dataset1 : public IEditableDataset<IStatistics> {};

// Наследует IReadableDataset, IEditableDataset
class Dataset2 : public IEditableDataset<> {};
wota ★★ ()
Последнее исправление: wota (всего исправлений: 2)
Ответ на: комментарий от wota

Один хрен не выходит каменный цветок:

#include <iostream>
#include <string>
using namespace std;


class IReadableDataset 
{
public:
	virtual string sayReadable() const = 0;
};



// Первый из двух родителей для Dataset1
template <typename T=IReadableDataset>
class IEditableDataset : public T
{
public:
	virtual string sayEditable() const = 0;
};

// Второй из двух родителей для Dataset1
class IStatistics : public IReadableDataset
{
public:
	virtual string sayStatistics() const = 0;
};

class Dataset : public IEditableDataset<IStatistics> {
public:
	virtual string sayReadable() const;
	virtual string sayEditable() const;
	virtual string sayStatistics() const;
};

std::string Dataset::sayReadable() const
{
	return "Readable";
}

std::string Dataset::sayEditable() const
{
	return "Editable";
}

std::string Dataset::sayStatistics() const
{
	return "Statistics";
}

int main()
{
	Dataset* dataset = new Dataset;
	cout << dataset->sayReadable() << endl;
	cout << dataset->sayEditable() << endl;
	cout << dataset->sayStatistics() << endl;

	cout << "==STATS==" << endl;
	IStatistics* statistics = dynamic_cast<IStatistics*>(dataset);
	cout << statistics->sayReadable() << endl;
	cout << statistics->sayStatistics() << endl;

	cout << "==DATASET==" << endl;

	IEditableDataset<IReadableDataset>* editable = dynamic_cast<IEditableDataset<IReadableDataset>*>(dataset);
	cout << (editable != 0) << endl;
	//дальше рушится
	cout << editable->sayEditable() << endl;
	cout << editable->sayReadable() << endl;

	return 0;
}
Yak ()
Ответ на: комментарий от wota

Обратно не то, что надо:

Я хочу, чтобы из IReadableDataset было видно только sayReadable, из IEditable - sayReadable и sayEditable, а из IStatistics - только sayReadable и sayStatistics.

Ну и чтобы реализация реально реализовывала все три метода.

Но всё вотще.


#include <iostream>
#include <string>
using namespace std;


class IReadableDataset 
{
public:
	virtual string sayReadable() const = 0;
};



// Первый из двух родителей для Dataset1
template <typename T=IReadableDataset>
class IEditableDataset : public T
{
public:
	virtual string sayEditable() const = 0;
};

// Второй из двух родителей для Dataset1
class IStatistics : public IReadableDataset
{
public:
	virtual string sayStatistics() const = 0;
};

class Dataset : public IEditableDataset<IStatistics> {
public:
	virtual string sayReadable() const;
	virtual string sayEditable() const;
	virtual string sayStatistics() const;
};

std::string Dataset::sayReadable() const
{
	return "Readable";
}

std::string Dataset::sayEditable() const
{
	return "Editable";
}

std::string Dataset::sayStatistics() const
{
	return "Statistics";
}

int main()
{
	Dataset* dataset = new Dataset;
	cout << dataset->sayReadable() << endl;
	cout << dataset->sayEditable() << endl;
	cout << dataset->sayStatistics() << endl;

	cout << "==STATS==" << endl;
	IStatistics* statistics = dynamic_cast<IStatistics*>(dataset);
	cout << statistics->sayReadable() << endl;
	cout << statistics->sayStatistics() << endl;

	cout << "==DATASET==" << endl;

	IEditableDataset<IStatistics>* editable = dynamic_cast<IEditableDataset<IStatistics>*>(dataset);
	cout << (editable != 0) << endl;
	cout << editable->sayEditable() << endl;
	cout << editable->sayReadable() << endl;
	cout << editable->sayStatistics() << endl;// не-не-не, я не хочу, чтобы этот метод был виден из IEditable!

	return 0;
}

Yak ()
Ответ на: Обратно не то, что надо: от Yak

А чем обычное

struct R {
    virtual string r() const = 0;
    virtual ~R() {}
};

struct W : public R {
    virtual string w() const = 0;
    virtual ~W() {}
};

struct S : public R {
    virtual string s() const = 0;
    virtual ~S() {}
};

class D : public W, public S {

  public:

    virtual string r() const { return "r"; }
    virtual string w() const { return "w"; }
    virtual string s() const { return "s"; }

};

int main()
{
    D d;
    cout << d.r() << " " << d.w() << " " << d.s() << endl;
    S &s = d;
    cout << s.r() << " " << s.s() << endl;
    W &w = d;
    cout << w.r() << " " << w.w() << endl;
}

не подходит?

quasimoto ★★★★ ()

Мало того что у вас не правильно спроектирована иерархия классов, так вы хотите ещё и шаблоны навернуть?

no-such-file ★★★★★ ()

НИчего не понял, но да - если для работы с этими шнягами юзать параметризованные ф-ии/классы, то можно вообще обойтись без наследования;-)

AIv ★★★★★ ()

Почитай про паттерны проектирования, чтобы не плодить велосипеды. Да, иерархия классов ужасна.

unfo ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.