Можно ли получить атрибут класса одновременно с классом?
Я прошу сделать Vec, который наследует от ABR. Этот ABR получил 3 указателя в качестве атрибута с типом ABR. Я хотел бы знать, могут ли эти указатели типа стать Vec при преобразовании в Vec без параметров шаблона?
вот код Соммы, чтобы изобразить это:
class Base
{
protected:
Base* x;
public:
Base(): x(nullptr){}
Base* getVal() {return x;}
};
class Derived: public Base
{
private:
int y;
public:
Derived():Base(), y(-1) {}
Derived(int Y): y(Y){}
Derived* getVal() {return x;}
void setVal(Derived *ptr){this->x = ptr;}
};
int main()
{
Derived D(5), c(7),*ptrToC=&c;
D.setVal(ptrToC);
D.getVal();
}
Этот код вернет ошибку в "D.getVal()", потому что x по-прежнему является указателем Base, поэтому возможно ли сделать так, чтобы он имел тот же тип, что и класс, в котором он находится?
2 ответа
Здесь есть способы, будь то простой полиморфизм или шаблоны.
Способ полиморфизма:
В Derived
объект, x
член, будучи объявлен Base *
будет действительно указывать только на Derived
объекты, потому что его значение может быть установлено только в Derived *
, Так что безопасно бросить его в getVal
:
...
Derived* getVal() {return static_cast<Derived *>(x);}
...
Шаблонный способ.
Вы можете использовать любопытно повторяющийся шаблон (CRTP) здесь:
template<class T>
class Base
{
protected:
T* x;
public:
Base(): x(nullptr){}
T* getVal() {return x;}
};
class Derived: public Base<Derived> {
private:
int y;
public:
Derived():Base(), y(-1) {}
Derived(int Y): y(Y){}
Derived* getVal() {return x;}
void setVal(Derived *ptr){this->x = ptr;}
};
Единственная возможность сделать это - шаблоны. Как способ - CRTP идиома:
template <class T>
class Base
{
protected:
Base* x;
public:
Base() : x(nullptr) {}
T* getVal() { return dynamic_cast<T*>(x); }
virtual ~Base() {}
};
class Derived : public Base<Derived>
{
private:
int y;
public:
Derived() :Base(), y(-1) {}
Derived(int Y) : y(Y) {}
void setVal(Derived *ptr) { this->x = ptr; }
};
int main()
{
Derived D(5), c(7), *ptrToC = &c;
D.setVal(ptrToC);
D.getVal();
}
Также обратите внимание, что в вашем коде нет полиморфизма. Вам нужно создать таблицу виртуальных функций для Base
добавив хотя бы один виртуальный метод (например, деструктор). если, конечно, вы не хотите разыграть Base на Derived