【问题标题】:pointers to object and descendants in C++C++中指向对象和后代的指针
【发布时间】:2015-09-20 14:24:27
【问题描述】:

我正在开发一个简单的 C++(在 Linux 下)项目,该项目将具有指向对象的指针。我有 A 类、扩展 A 的 B 类和扩展 B 的 C 类。C 类有一个在 A 或 B 中不存在的方法(测试)。

是否有可能有一个指针“p”可以指向 A、B 和 C 类型的对象?我将如何定义该指针?

其次,由于 a.test() 不存在,但 c.test() 存在,我的通用指针 'p' 可以调用 p->test() 吗?这会编译吗?如果在运行时 p 指向 A 类的对象并且我调用 p->test() 怎么办?这是运行时错误吗?

【问题讨论】:

  • 查找多态性
  • 我查过多态性,大多数网站都在谈论重载。当涉及到继承和指针时,信息并不那么清楚。这很接近:stackoverflow.com/questions/15188894/… 但仍不确定。我混淆了一些东西,这使得它比应有的更难掌握。
  • 你见过this吗?
  • 您可能已经查找过多态性,但您显然还没有充分理解其含义。根据您的描述,指向A(即A * 类型)的指针可以指向B 或C。如果A 是一个多态基,那么在C++ 中,它提供了一组可由B 或C 专门化的虚函数。如果您设计的这样一个类层次结构(特别是基类A)足够好,则不需要强制转换。事实上,需要转换通常表示设计错误。

标签: c++ class casting descendant


【解决方案1】:

有可能有一个指针可以指向一个对象 类型 A、B 和 C?

我假设您的意思是 “可以指向 A 对象或 B 对象或 C 对象”,对吗?

是的,你可以有这样的指针。

如何定义该指针?

A*

基类指针可以指向派生类的对象。

其次,如果指针可以,我将如何调用对象的方法 指向 A/B/C 类?

您在A 中定义一个virtual 函数并在B 和C 中覆盖它。然后,当您通过A* 调用该方法时,该语言将执行动态调度,即它会根据您的A* 是指向A、B 还是指向C.

我需要在调用方法之前强制转换它们吗?

没有。这将大大违背虚函数的目的。

这是一个完整的例子:

#include <iostream>

class A
{
public:
    virtual ~A() {} // not really needed in this program,
                    // but almost always needed in real code
                    // when a class has a virtual function
    virtual void method() { std::cout << "A::method\n"; }
};

class B : public A
{
public:
    virtual void method() override { std::cout << "B::method\n"; }
};

class C : public A
{
public:
    virtual void method() override { std::cout << "C::method\n"; }
};

int main()
{
    A a;
    B b;
    C c;
    A* ptr = &a;
    ptr->method();
    ptr = &b;
    ptr->method();
    ptr = &c;
    ptr->method();
}

输出:

A::method
B::method
C::method

【讨论】:

  • 如果派生类的动态分配实例(使用运算符new 创建)通过指向基类的指针被销毁(运算符delete),则需要虚拟析构函数以避免未定义的行为。这不需要存在其他虚函数(尽管在实践中,这些类通常会有虚函数)。
  • @Peter:没错。我不认为我曾经编写或维护过 only 析构函数是虚拟的基类。我什至想不出一个好的用例。
  • 谢谢!越来越清晰。我是否必须定义虚函数?如果我的基类是 ANIMAL,派生类是 DOG 和 CAT,那么基类真的需要 bark() 和 meow() 方法吗?这使我的代码不那么整洁。有什么办法吗?
  • @Telium:吠叫和喵喵叫不是抽象的,属于任何动物的普遍事物。所以你会不将它们放入Animal 基类中,不。一个基类可能有一个类似makeNoise 的方法,并且您可以根据派生类中的吠叫或喵喵叫来实现它。这将引导您发现纯虚函数,因为抽象动物不会发出明确的噪音​​。因此,您可以像这样声明基本方法:virtual void makeNoise() = 0;。但是你真的应该阅读更多关于这方面的教材。
  • 好了,快到了!我读过我可以将方法添加到派生类(基类中不存在)。这就是我卡住的地方!所以如果类 BIRD 派生自 ANIMAL,那么 BIRD 可以有一个 fly 方法(它不会存在于基类中)。但是现在如果我有一个指向基类的指针,如果我调用 fly 方法会发生什么?这会编译吗?如果实例是一只狗,而我称它为 fly 怎么办? 这是我困惑的地方
猜你喜欢
  • 1970-01-01
  • 2021-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-02
相关资源
最近更新 更多