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

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

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
}

В приведенном выше коде, насколько я знаю, есть вещи, которые не относятся к c ++, они тесно связаны с сопоставлением с образцом, найденным, например, в Haskell, но это лучший способ проиллюстрировать мой вопрос, даже не зная, ответ;)

В письменном виде я хочу, чтобы клиент мог создавать базовый объект и передавать тип объекта в качестве аргумента, возвращается правильная спецификация объекта, и клиенту не нужно заботиться об этом, он просто знает, что работает render будет запускать правильный конкретный рендер.

Пожалуйста, не стесняйтесь задавать вопросы, если мне было неясно:)

Ответы [ 4 ]

3 голосов
/ 08 сентября 2011

Я думаю, вам нужно прочитать о виртуальных функциях и наследовании:

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

2 голосов
/ 08 сентября 2011

Вам нужен полиморфизм времени выполнения . Там не так много важной части конструктора. Вы должны наследовать 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;
1 голос
/ 08 сентября 2011

Я не уверен, что понял ваш вопрос. В 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
}

Надеюсь, что это отвечает на ваш вопрос.

0 голосов
/ 08 сентября 2011

То, что вы просите, это именно то, для чего предназначено наследование: создание объекта из иерархии классов, которая специализирует функциональность.

В вашем примере, кроме проблем с синтаксисом, все будет работать так, как вы ожидаете, то есть будет вызван метод A::render, даже если вы не знаете во время компиляции, что объект, объявленный как Base, действительно A. Это волшебство виртуального наследства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...