以下代码: https: //godbolt.org/z/eYEdTnMqc
#include<memory>
#include<vector>
#include<string>
class Base {
protected:
std::string type;
};
class Derived1 : public Base{
protected:
bool status;
public:
Derived1(): status(false), type("Derived1") {}
void setStatus(bool newStatus) {
status = newStatus;
}
bool getStatus() {
return status;
}
};
int main() {
std::vector<std::shared_ptr<Base>> vars;
vars.push_back(std::make_shared<Derived1>());
if(!vars.back()->getStatus()) {
vars.back()->setStatus(true);
}
}
Run Code Online (Sandbox Code Playgroud)
给我这个编译错误:
Could not execute the program
Compiler returned: 1
Compiler stderr
<source>: In constructor 'Derived1::Derived1()':
<source>:13:32: error: class 'Derived1' does not have any field named 'type'
13 | Derived1(): status(false), type("Derived1") {}
| ^~~~
<source>: In function 'int main()':
<source>:26:20: error: 'using element_type = class Base' {aka 'class Base'} has no member named 'getStatus'
26 | if(!vars.back()->getStatus()) {
| ^~~~~~~~~
<source>:27:18: error: 'using element_type = class Base' {aka 'class Base'} has no member named 'setStatus'
27 | vars.back()->setStatus(true);
| ^~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
我的基类有其他没有 getStatus() 和 setStatus() 方法的派生类,因此我不想在基类中将它们设为虚拟。
EDIT1:我编辑了代码并编译错误,以清除我的愚蠢错误,同时保持这个问题的主旨和解决方案完好无损。基本上我需要使用 std::shared_ptr 并在访问向量内的项目时使用 std::static_pointer_cast 。谢谢@雷米
编辑2:正如@remy 下面指出的那样, static_cast/dynamic_cast 到原始指针很好,因为我不打算共享所有权。所以我应该恢复到 std::unique_ptr 并使用dynamic_cast。所以解决方案是下面的代码:
https://godbolt.org/z/4Yz94z7bb
#include<memory>
#include<vector>
#include<string>
class Base {
protected:
std::string type;
};
class Derived1 : public Base{
protected:
bool status;
public:
Derived1(): status(false) {}
void setStatus(bool newStatus) {
status = newStatus;
}
bool getStatus() {
return status;
}
};
int main() {
std::vector<std::unique_ptr<Base>> vars;
vars.push_back(std::make_unique<Derived1>());
static_cast<Derived1*>(vars.back().get())->setStatus(true);
}
Run Code Online (Sandbox Code Playgroud)
在您显示的代码中,Derived1实际上并不派生自Base,因此您无法将Derived1*指针分配给Base*指针,因此无法将 astd::unique_ptr<Derived1>移至std::unique_ptr<Base>。
改变这个:
class Derived1 {
Run Code Online (Sandbox Code Playgroud)
对此:
class Derived1 : public Base {
Run Code Online (Sandbox Code Playgroud)
然后,为了更好地衡量,您应该标记Derived1::getStatus()为override:
bool getStatus() override {
return status;
}
Run Code Online (Sandbox Code Playgroud)
Base现在,话虽这么说,由于您在 中存储指针vector,您的代码仍然无法编译,因为setStatus()中没有定义方法Base,因此此语句无效:
vars.back()->setStatus(true);
Run Code Online (Sandbox Code Playgroud)
vars.back()将返回对对象的引用std::unique_ptr<Base>,然后调用operator->该对象将返回一个Base*指针,而不是Derived1*指针。因此,您需要将Base*指针强制转换回Derived1*才能访问该Derived1::setStatus()方法:
static_cast<Derived1*>(vars.back().get())->setStatus(true);
Run Code Online (Sandbox Code Playgroud)
您应该添加一个虚拟setStatus()方法来Base覆盖Derived1。那么你就不再需要演员了:
class Base {
public:
virtual bool getStatus() {
return false;
}
virtual void setStatus(bool newStatus) {
}
};
class Derived1 : public Base {
protected:
bool status;
public:
Derived1(): status(false) {}
bool getStatus() override {
return status;
}
void setStatus(bool newStatus) override {
status = newStatus;
}
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
621 次 |
| 最近记录: |