【问题标题】:Override Methods in C/C++ like Delphi覆盖 C/C++ 中的方法,如 Delphi
【发布时间】:2011-02-28 21:36:34
【问题描述】:

在 Delphi 中,我们可以选择执行以下操作:

TClass1 = class
  procedure Test; virtual;
end;

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

所以在代码中,如果我创建一个 TClass2 的实例,即使我将对象转换为:

TClass1(ObjectClass2).Test;

应用程序将调用在 TClass2 上声明的函数。

但是在 C/C++ 中我找不到这样做的方法。

如果我将一些 void 声明为虚拟,并在我对父类进行强制转换时在子类中实现相同的 void,它将不会使用子类的实现。

有谁知道我如何在 C/C++ 中重现 Delphi 的行为?


新信息: 这些是我的文件。

---------------------- 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;
}

【问题讨论】:

  • 你描述的应该可以。向我们展示您的 C++ 代码。
  • 我将利用我的午餐时间发布我的代码并验证答案,tks in advice
  • @saCi 不同之处在于您正在创建基于堆栈的对象。如果您按照我的回答和 birryree 的回答在堆上创建对象,那么它的行为将与 Delphi 一样,并且如您所愿。
  • 感谢 David Haffernan,我明白其中的区别。我会接受 biryree 的回答,因为他先发帖。但是感谢您的解释和耐心。
  • @Saci - 我看到您更新了执行此操作的代码:((Pai)filho).metodoX();。因此,当您这样做时,您不会使用对基类的指针/引用。您只是将 filho 对象转换为 Pai 对象。这不会导致多态函数调用,而只会调用Pai::metodoX() 函数。如果您改为这样做:((Pai*)filho)-&gt;metodoX();,它将多态地调用FilhometodoX()。我已经用这个更新了我的答案。

标签: c++ delphi


【解决方案1】:

我不是 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();

它将多态地调用FilhometodoX()

【讨论】:

  • +1 Delphi 只有堆分配的引用对象,如 Java 和 C#。我猜 OP 的问题是由于使用了基于堆栈的对象。您在回答中已经非常清楚地说明了这一切。
  • @David - 感谢您告诉我,我不知道 Delphi。
【解决方案2】:

在 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 中不支持基于堆栈的对象的唯一方法。

【讨论】:

    【解决方案3】:
    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(){}
    };
    

    【讨论】:

      猜你喜欢
      • 2011-09-15
      • 2010-11-16
      • 1970-01-01
      • 2016-10-29
      • 1970-01-01
      • 2012-02-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多