Как сделать абстракцию для базового класса с помощью виртуальных функций?
У меня следующая структура
class Base
{
public:
Base(Type);
virtual render
}
class A
{
public:
Base(Type == A);
void render()
}
class B
{
public:
Base(Type == B);
void render()
}
void client_function()
{
Base baseObject(A);
//Base is an instance of class A
baseObject.render()//runs class A render
}
В приведенном выше коде, насколько я знаю, есть вещи, которые не являются с ++, они тесно связаны с сопоставлением с образцом, найденным, например, в Haskell, но это лучший способ, который я смог найти, чтобы проиллюстрировать мой вопрос, не зная ответа;)
При написании статьи я хочу, чтобы клиент мог создавать базовый объект и передавать тип объекта в качестве аргумента, возвращается правильная спецификация объекта, и клиенту не нужно заботиться об этом, он просто знает, что при запуске render будет выполняться правильный конкретный рендер.
Пожалуйста, не стесняйтесь задавать вопросы, если мне было неясно:)
4 ответа
Я думаю, вам нужно прочитать о виртуальных функциях и наследовании:
http://www.parashift.com/c++-faq-lite/virtual-functions.html
http://www.parashift.com/c++-faq-lite/proper-inheritance.html
Вам нужен полиморфизм во время выполнения. Там не так много важной части конструктора. Вы должны унаследовать Base
в A
а также B
, Например:
class Base
{
public:
virtual void render (); // <--- declare 'virtual'
virtual ~Base(); // <--- very much needed to avoid undefined behavior
};
class A : public Base //<---- inheritance
{
public:
void render(); // <--- this also becomes 'virtual'
};
...
Теперь вы можете использовать согласно вашему требованию.
Base *baseObject = new A(); // <----- need to use pointer (or reference)
(*baseObject).render(); // <--- other way to write: baseObject->render();
delete baseObject;
Я не уверен, что понял ваш вопрос. В C++ вы не можете выбирать свой базовый класс во время выполнения, но вы наверняка можете иметь свой базовый класс в зависимости от производного класса. Это делается с помощью шаблонов и того, что известно как шаблон с любопытством повторяющихся шаблонов:
template <typename T> class Base {
public:
virtual void render(T *) {}
};
class A : public Base<A>
{
public:
void render(A * t) {}
};
class B : public Base<B>
{
public:
void render(B * t) {}
};
void client_function() {
A a1;
A a2;
a1.render(&a2); // calls A::render
a1.Base<A>::render(&a2); // calls Base<A>::render
Base<A> * ba = &a1;
ba->render(&a2); // calls A::render
}
Надеюсь, что это ответ на ваш вопрос.
То, что вы просите, это именно то, для чего предназначено наследование: создание объекта из иерархии классов, которая специализирует функциональность.
В вашем примере, кроме проблем с синтаксисом, все будет работать так, как вы ожидаете, то есть метод A::render
будет вызван, даже если вы не знаете во время компиляции этот объект, объявленный как Base
действительно A
, Это виртуальное наследство волшебства.