gpt4 book ai didi

c++ - 从派生类调用带有抽象基类的类——安全

转载 作者:行者123 更新时间:2023-12-05 03:31:04 28 4
gpt4 key购买 nike

我想调用类 Foo,它的构造函数中有抽象类 Base。我希望能够从派生自 BaseDerived 调用 Foo 并使用 Derived覆盖方法而不是 Base 的方法。

我只能按照指示使用原始指针来执行此操作。没有原始指针,有什么办法可以做到这一点吗?我试过 std::shared_ptr 但编译器提示抽象类。或者有更好的方法吗?

#include <iostream>

class Base {
public:
Base() {
std::cout << "Hello from Base." << std::endl;
}

virtual void show() const = 0;
};

class Foo {
public:
explicit Foo(const Base *s) { // can I avoid this raw pointer?
std::cout << "Hello from Foo." << std::endl;
s->show();
}
Base *s;
};

class Derived : public Base {
public:
Derived() : Base() {
std::cout << "Hello from Derived." << std::endl;
Foo(this);
}

void show() const override {
std::cout << "Hi, I'm Derived::show()." << std::endl;
}
};

int main() {
Derived();
return EXIT_SUCCESS;
}

产生以下输出:

Hello from Base.
Hello from Derived.
Hello from Foo.
Hi, I'm Derived::show().

最佳答案

代码可以用对 Base 的 const 引用重写为

#include <iostream>

class Base {
public:
Base() {
std::cout << "Hello from Base." << std::endl;
}

virtual void show() const = 0;
};

class Foo {
public:
explicit Foo(const Base& b) : s(b) { // member initialization list to set s
std::cout << "Hello from Foo." << std::endl;
s.show();
}
const Base& s;
};

class Derived : public Base {
public:
Derived() : Base() {
std::cout << "Hello from Derived." << std::endl;
Foo(*this); // the parameter would be the object itself *this, instead of a pointer this
}

void show() const override {
std::cout << "Hi, I'm Derived::show()." << std::endl;
}
};

int main() {
Derived();
return EXIT_SUCCESS;
}

引用应该在构造函数的成员初始化列表中初始化。

当使用原始指针或引用时,“Foo”不应拥有“Base”,即 Foo 不负责销毁 Base 的生命周期Base 应由 Foo 的所有者保证。您必须确保 Base(在本例中为 =Derived)比 Foo 长。这是有保证的,如果 Foo 对象由 Derived 拥有,例如作为成员或局部变量。然后在Base=Derived被销毁之前,Foo被销毁。

您可以使用普通引用而不是 const 引用,但对于构​​造函数参数和成员变量也是如此。

原始指针(与引用相比)在某些情况下是惯用的,

  1. 参数也可以是nullptr而不是有效对象或
  2. 指针在对象的生命周期中与另一个指针交换的地方。

第一种情况可以由 std::optional 来处理,第二种情况可以分配一个轻量级对象('view'),它基本上封装了一个指针或引用。

因此,在极少数情况下(例如低级代码、数据结构或与 C 兼容),原始指针仍将在现代 C++ 中使用。即使在这些情况下,拥有一个仅将引用存储为成员变量的包装器对象也将具有与原始指针相同的性能(实际上也具有相同的内存布局),但使用起来更加干净和安全。

在某些情况下,当执行速度或内存大小非常重要时,出于性能原因,您更喜欢指向 std::optional 的原始指针。作为替代方案,C++ 中不允许引用 nullptr

关于c++ - 从派生类调用带有抽象基类的类——安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70711684/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com