多态unique_ptr类成员
Polymorphic unique_ptr class member
我希望有一个指向基类的unique_ptr类成员,但稍后在构造函数中可以通过多态性更改为指向也派生自同一基类的姐妹类。
虽然我在构造函数设置此多态性时没有收到任何错误,但它似乎无法正常工作,因为我收到错误消息,指出我的多态指针找不到我认为指针现在指向的姐妹类的成员。
如何在此处正确实现多态性?
class A {
int bar;
};
class B : public A {
int foo;
};
class C: public A {
C();
std::unique_ptr<A> _ptr; // changing to std::unique_ptr<B> _ptr removes the "class A has no member 'foo'" error
};
C::C() : A()
{
_ptr = std::make_unique<B>(); // no errors here
int w = _ptr->foo; // class A has no member 'foo'
}
当您分配时
_ptr = std::make_unique<B>();
这是有效的B
因为它是A
的派生类,但是_ptr
仍然是基类的unique_ptr
。声明变量后,无法更改变量的类型。
那么你有什么选择呢?
因为您知道_ptr
存储指向派生类B
的指针,所以您可以在取消引用它后进行强制转换:
_ptr = std::make_unique<B>();
// derefence the pointer, and cast the reference to `B&`.
B& reference_to_sister = (B&)(*_ptr);
int w = reference_to_sister.foo;
如果你采用这种方法,你必须以某种方式跟踪哪个派生类在_ptr
,否则你将面临遇到错误的风险。
或者,如果您使用的是 C++17,则可以使用 std::variant
:
class C : public A {
void initialize(A& a) {
// Do stuff if it's the base class
}
void initialize(B& b) {
// Do different stuff if it's derived
int w = b.foo;
}
C() {
_ptr = std::make_unique<B>(); // This works
// This takes the pointer, and calls 'initialize'
auto initialize_func = [&](auto& ptr) { initialize(*ptr); };
// This will call 'initialize(A&)' if it contains A,
// and it'll call 'initialize(B&)' if it contains B
std::visit(initialize_func, _ptr);
}
std::variant<std::unique_ptr<A>, std::unique_ptr<B>> _ptr;
};
事实上,如果你使用std::variant
即使A
和B
是完全不相关的类,这也将起作用。
这是另一个简短的variant
示例
#include <variant>
#include <string>
#include <iostream>
void print(std::string& s) {
std::cout << "String: " << s << 'n';
}
void print(int i) {
std::cout << "Int: " << i << 'n';
}
void print_either(std::variant<std::string, int>& v) {
// This calls `print(std::string&) if v contained a string
// And it calls `print(int)` if v contained an int
std::visit([](auto& val) { print(val); }, v);
}
int main() {
// v is empty right now
std::variant<std::string, int> v;
// Put a string in v:
v = std::string("Hello, world");
print_either(v); //Prints "String: Hello, world"
// Put an int in v:
v = 13;
print_either(v); //Prints "Int: 13"
}
相关文章:
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 助记符和指向成员语法的指针
- 用于访问容器<T>数据成员的正确 API
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 嵌套在类中时无法设置成员数据
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 将函数类成员映射到类本身内部
- 初始pointCloudt :: PTR类成员
- 通过成员函数将唯一 ptr 的向量附加到另一个向量
- LNK 2001 未解析的外部在 NPPluginFuncs 结构 ptr 作为静态类成员
- 我应该通过引用、值或ptr来存储一个完全封装的成员吗
- 从虚拟成员函数ptr中进行类型推导(bug?)
- 一个唯一的ptr类如何将它的实例指针传递给它的成员对象
- ptr到成员模板参数的友元语法