C++ 继承抽象函数
c++ inheritance abstract function?
我有一个关于继承的基本问题,我似乎可以弄清楚,我已经进行了搜索但没有找到我要找的东西,所以我想我会在这里问(不确定我正在寻找的标题是否正确)。
为了简单起见,我制作了一些示例代码来说明我没有得到的东西。
基本上,如果我有一个父class A
和两个子类B
C
,其中A
包含常见内容(例如带有get/set的id
),而B
和C
具有特定于类的功能。如果你声明一个类B
如下:A *bObject = new B();
how do you then access the class specific function
bObj->specific()'?
我已经尝试过virtual
但这需要B
和C
声明相同的函数名称/原型。我也尝试过在A
中声明摘要,但这需要它是原型才能在A
中。
我哪里出错了? 对此的任何帮助,可能是基本问题都会有所帮助。
#include <iostream>
using namespace std;
// A class dec
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
};
// B class dec - child of A
class B :
public A
{
public:
B(void);
~B(void);
void sayHello();
};
//C class dec - child of A
class C :
public A
{
public:
C(void);
~C(void);
void sayGoodby();
};
//a stuff
A::A(void)
{
}
A::~A(void)
{
}
void A::setId(char id)
{
this->id = id;
}
char A::getId()
{
return this->id;
}
//b stuff
B::B(void)
{
this->setId('b');
}
B::~B(void)
{
}
// c stuff
C::C(void)
{
this->setId('c');
}
C::~C(void)
{
}
void C::sayGoodby()
{
std::cout << "Im Only In C" << std::endl;
}
// main
void main ()
{
A *bobj = new B();
A* cobj = new C();
std::cout << "im class: " << bobj->getId() << endl;
bobj->sayHello(); // A has no member sayHello
std::cout << "im class: " << cobj->getId() << endl;
cobj->sayGoodby(); // A has no member sayGoodby
system("PAUSE");
}
谢谢你的时间!
若要访问派生类特有的方法,需要先将基类指针强制转换为正确的派生类类型(向下转换):
A *bobj = new B();
bobj->sayHello(); // compile error
dynamic_cast<B*>(bobj)->sayHello(); // works
dynamic_cast<C*>(bobj)->sayGoodbye(); // run-time error - probably crashes with a segfault/access violation.
dynamic_cast
可确保运行时类型安全,但会给强制转换增加少量开销;对于指针强制转换,如果指向的对象实际上不是 B,则返回 null 指针,您应该在使用它之前检查返回值。或者,如果您确实确定要转换的指针指向正确的对象,则可以使用 static_cast
来节省运行时检查的成本,但如果指针未指向正确的对象,则会得到未定义的行为。
A *bobj = new B();
A* cobj = new C();
这里 B 和 C 的实例由 A 的指针指向。由于 A 没有 B 的虚函数和 C 的成员函数 sayHello() 和 sayGoodbye(),因此它们无法被 bobj->sayHello()
和 cobj->sayGoodbye()
调用。这不是多态性应该做的事情。
A类应为:
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
virtual void sayHello(){/* to do */ };
virtual void sayGoodbye(){ /* to do */ };
};
然后可以调用bobj->sayHello();
和cobj->sayGoodbye();
而无需计划。
A *bobj = new B();
bobj
的静态类型为 A *
。因此,在编译时,编译器会在类A
定义中查找成员函数,即您尝试通过bobj
访问的内容。现在
bobj->sayHello();
编译器将在类 A
中查找sayHello
,因为bobj
的类型是 A *
。编译器不关心查看类B
定义来解决调用。由于编译器没有找到它sayHello
A
的成员,它正在抱怨。
但是,bobj
的动态类型是B *
,即根据动态类型调度调用的位置。
要解决此问题,您需要在类 A
中virtual
相同的函数。
如果你真的想调用这样的函数,你可以这样做:
A* bobj = new B();
((B*)bobj)->sayHello();//this can be dangerous if bobj is not an instance of class B
但是,这里的问题是你做错了设计。基本上,如果您创建一个类 A,并将其子类化为 B 和 C。然后分配 A* bobj = 新的 B();您正在拆分接口和实现。这意味着你将使用 bobj,就好像它是类 A 的实例一样,你不会调用 B 或 C 中的函数。
这就像你雇人来盖房子一样。你给他们你的蓝图(接口)并雇用他们来构建。您可以根据需要更改蓝图,他们将在蓝图中执行任何操作。但是你不能直接订购它们(就像你不能直接从 bobj 调用 sayHello() 一样)。
您可以通过 dynamic_cast<>
使用向下投射。您可以在基类A
中实现模板方法,以便于向下转换:
class A
{
public:
A(void);
virtual ~A(void);
char id;
void setId(char id);
char getId();
template <typename CHILD, typename R, typename... ARGS>
R invoke (R (CHILD::*m)(ARGS...), ARGS... args) {
CHILD *child = dynamic_cast<CHILD *>(this);
if (child) return (child->*m)(args...);
std::cout << "down cast error: " << typeid(CHILD).name() << std::endl;
}
};
如果A
的特定实例不是CHILD
的基础,那么dynamic_cast<CHILD *>(this)
导致NULL
。 请注意,A
中的虚拟析构函数是dynamic_cast<>
工作所必需的。
因此,您可以像这样使用它:
std::unique_ptr<A> bobj(new B());
std::unique_ptr<A> cobj(new C());
bobj->invoke(&B::sayHello);
bobj->invoke(&C::sayGoodbye);
cobj->invoke(&B::sayHello);
cobj->invoke(&C::sayGoodbye);
只有第一次和最后一次调用有效。中间的两个将导致打印"down cast error"
消息。
- C++虚函数继承
- 名称隐藏对静态函数继承的实例使用
- 从抽象类继承以创建另一个抽象类时,我应该重新声明所有虚函数吗?
- C++ std::vector 中的虚拟析构函数继承
- 设计模式,以避免不必要地添加抽象函数以适应新功能
- 具有相同名称的类的构造函数继承
- 多复制构造函数继承中的惊人行为
- C++的抽象类继承和构造函数的问题
- C++:抽象类继承和构造
- 为每个抽象函数定义主体后,对VTable的不确定引用
- CRTP 和复制/移动赋值/构造函数继承
- 复制构造函数继承动态分配的数组
- 从抽象类继承的类的实例
- 谷神星求解器成本函数继承错误:模板可能不是虚拟的
- 使用继承的函数而不是基函数(不是抽象函数)
- C++通过继承函数实现继承的抽象函数
- C++ 继承抽象函数
- C++非抽象析构函数继承
- c++继承与抽象函数实现
- c++中的抽象类、函数继承和覆盖