在Delphi中,我们可以选择这样做:
TClass1 = class
procedure Test; virtual;
end;
TClass2 = class(TClass1)
procedure Test; override;
end;
所以在代码中,如果我创建了一个TClass2的实例,即使我将对象转换为:
TClass1(ObjectClass2).Test;
应用程序将调用在TClass2上声明的函数。
但是在C / C ++中,我找不到办法做到这一点。
如果我将一些void声明为virtual并在我对父类进行强制转换时在子类中实现相同的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;
}
答案 0 :(得分:8)
我不是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 = ≻
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
的{{1}}。
答案 1 :(得分:6)
在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中不支持基于堆栈的对象的唯一方法。
答案 2 :(得分:1)
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(){}
};