Методы переопределения в C / C ++, такие как Delphi - PullRequest
2 голосов
/ 01 марта 2011

В Delphi у нас есть возможность сделать что-то вроде этого:

TClass1 = class
  procedure Test; virtual;
end;

TClass2 = class(TClass1)
  procedure Test; override;
end;

Так в коде, если я создаю экземпляр TClass2, даже если я приведу объект как:

TClass1(ObjectClass2).Test;

Приложение вызовет функцию, объявленную в TClass2.

Но в C / C ++ я не смог найти способ сделать это.

Если я объявлю некоторый void виртуальным и реализую тот же void в дочернем классе, когда приведу приведение к родительскому классу, он не будет использовать реализацию дочернего класса.

Кто-нибудь знает, как я могу воспроизвести поведение Delphi в C / C ++?


Новая информация: Это мои файлы.

---------------------- File Filho.hpp
#ifndef FILHO_HPP
#define FILHO_HPP
#include "Pai.hpp"

class Filho : public Pai {
public:
    Filho();
    virtual ~Filho();
    void metodoX();
};

Filho::Filho() {}
Filho::~Filho() {}

void Filho::metodoX() {
    std::cout << "Hello Filho!" << std::endl;
}
#endif


---------------------- File Pai.hpp
#ifndef PAI_HPP
#define PAI_HPP
#include <iostream>

class Pai {
public:
    Pai();
    virtual ~Pai();
    virtual void metodoX();
};
Pai::Pai() {}
Pai::~Pai() {}

void Pai::metodoX() {
    std::cout << "Hello Pai!" << std::endl;
}

#endif

---------------------- File Main.hpp
#include "Pai.hpp"
#include "Filho.hpp"

int main() {
    Pai pai;
    pai.metodoX();      //Here output the msg Hello Pai!

    Filho filho;           
    filho.metodoX();    //Here output the msg Hello Filho!

    ((Pai) filho).metodoX(); //Here output the msg Hello Pai! , but here if I use the directive 'override' in Delphi, the output will be Hello Filho!. Here is my doubt.
    return 0;
}

Ответы [ 3 ]

8 голосов
/ 01 марта 2011

Я не эксперт по Delphi, но могу объяснить, как эти вещи ведут себя в C ++.

Таким образом, в C ++ у вас может быть класс, который определяет функцию virtual, что означает, что если вы используете указатель базового класса / ссылку на объект, эта функция может быть вызвана посредством динамической диспетчеризации (т. Е. Поиска функции времени выполнения) .

#include <iostream>

class BaseClass
{
public:
    virtual void virtFunc() { std::cout << "BaseClass\n"; } // notice the 'virtual' keyword
    void nonvirtFunc() { std::cout << "BaseClass\n"; }
};


class SubClass : public BaseClass
{
public:
   virtual void virtFunc() { std::cout << "SubClass\n"; }
   void nonvirtFunc() { std::cout << "SubClass\n"; }
};

int main()
{
    // You need to use base class pointers/references
    SubClass sc = SubClass();
    BaseClass *bcp = &sc;
    bcp->virtFunc(); // prints "SubClass"     
    bcp->nonvirtFunc(); // prints "BaseClass"   

    // doing it by allocating an object on heap
    BaseClass *dbcp = new SubClass();
    dbcp->virtFunc(); // prints "SubClass"
    dbcp->nonvirtFunc(); // prints "BaseClass"
    delete dbcp; // in a real program, you should have a virtual destructor which will be called from this code

    BaseClass bc = SubClass();
    bc.virtFunc(); // prints "BaseClass", and in more complex objects, slicing occurs
}

Новый код, который вы разместили

Я вижу, что вы обновили свой код, который делает это:

((Pai)filho).metodoX();

Поэтому, когда вы делаете это, вы не используете указатели / ссылки на базовый класс. Вы просто приводите объект filho к объекту Pai. Это не приводит к полиморфному вызову функции, а просто вызывает функцию Pai::metodoX().

Если вы сделали это вместо:

((Pai*)filho)->metodoX();

Это вызовет Filho metodoX() полиморфно.

6 голосов
/ 01 марта 2011

В C ++ вы написали бы:

class Class1
{
  public:
    virtual void Test();
};

class Class2: public Class1
{
  public:
    virtual void Test();
};

Class1* obj = new Class2();
obj->Test();//calls Class2.Test()

Это достигается так же, как в вашем примере Delphi.

Ключ заключается в создании объекта C ++ в куче и сохранении ссылки на негоЭто, конечно, единственный способ делать вещи в Delphi, который не поддерживает стековые объекты.

1 голос
/ 01 марта 2011
TClass1* obj = new TClass2 ;
obj->procedure();

Если TClass1 (базовый класс) и TClass2 (производный класс) имеют иерархические отношения (то есть наследование)

class TClass1
{
    public:
    virtual void procedure(){} // Assuming procedure's return type is void.
    virtual ~TClass1(){}
};

class TClass2 : public TClass1
{
    public:
    void procedure(){}
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...