Как сделать абстракцию для базового класса с помощью виртуальных функций?

У меня следующая структура

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

http://www.parashift.com/c++-faq-lite/abcs.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, Это виртуальное наследство волшебства.

Другие вопросы по тегам