c++ 将对纯虚拟 class 的引用存储为 class 的成员
c++ store a reference to a pure virtual class as member of class
我有一个包含 class 实例的模板化包装器,它继承了纯虚拟 class。
我的问题是如何将数据存储在包装器中。
- 我不能使用副本,因为纯虚拟 classes 无法实例化(如果我使用简单的虚拟 class 则无法切片)。
- 我没能留下参考资料。此引用无效,因为我不管理我获得的对象的分配(超出范围)。
- 我唯一的解决方案是使用指针,即使我想避免这种情况,因为这不是很安全,我需要我的代码是健壮的。
我能做什么?
这是一个模拟我的问题的小例子:
#include <iostream>
#include <string>
#include <ctime>
#include <cmath>
using namespace std;
class Module
{
public:
Module() : m(rand())
{
cout << "m = " << m << endl;
}
virtual void f() = 0;
int m;
};
class ModuleA : public Module
{
public:
ModuleA() : ma(rand())
{
cout << "ma = " << ma << endl;
}
void f() {}
int ma;
};
template<typename T>
class Container
{
public:
Container(T e) : element(e) {}
T element;
};
// Objects are created outside of main
ModuleA createModule()
{
return ModuleA();
}
Container<Module&> createContainer()
{
return Container<Module&>(createModule());
}
int main()
{
srand((unsigned int)time(NULL));
Container<Module&> conta = createContainer();
ModuleA& ca1 = dynamic_cast<ModuleA&>(conta.element); // wrong !
system("pause");
return 0;
}
您可以在容器中使用 std::shared_ptr
,即
template<typename T>
class Container
{
public:
// The pointer you get must be managed as well
Container(std::shared_ptr<T> e) : element(e) {}
std::shared_ptr<T> element;
};
那将是绝对安全的。实际上,如果对象超出创建它的代码的范围,您仍然有一个有效的指针,直到容器本身超出范围。如果 std::shared_ptr
的语义不完全适合您的情况,您可以进一步调整 std::weak_ptr
或 std::unique_ptr
的内存所有权关系。
你绝对应该研究一下 std::weak_ptr
,因为它允许你禁止某些代码获取指针的所有权,但仍然允许访问 if 指针有效在您需要访问它的位置。它还可以防止内存保留周期,因为 std::weak_ptr
不拥有内存。
我有一个包含 class 实例的模板化包装器,它继承了纯虚拟 class。
我的问题是如何将数据存储在包装器中。
- 我不能使用副本,因为纯虚拟 classes 无法实例化(如果我使用简单的虚拟 class 则无法切片)。
- 我没能留下参考资料。此引用无效,因为我不管理我获得的对象的分配(超出范围)。
- 我唯一的解决方案是使用指针,即使我想避免这种情况,因为这不是很安全,我需要我的代码是健壮的。
我能做什么?
这是一个模拟我的问题的小例子:
#include <iostream>
#include <string>
#include <ctime>
#include <cmath>
using namespace std;
class Module
{
public:
Module() : m(rand())
{
cout << "m = " << m << endl;
}
virtual void f() = 0;
int m;
};
class ModuleA : public Module
{
public:
ModuleA() : ma(rand())
{
cout << "ma = " << ma << endl;
}
void f() {}
int ma;
};
template<typename T>
class Container
{
public:
Container(T e) : element(e) {}
T element;
};
// Objects are created outside of main
ModuleA createModule()
{
return ModuleA();
}
Container<Module&> createContainer()
{
return Container<Module&>(createModule());
}
int main()
{
srand((unsigned int)time(NULL));
Container<Module&> conta = createContainer();
ModuleA& ca1 = dynamic_cast<ModuleA&>(conta.element); // wrong !
system("pause");
return 0;
}
您可以在容器中使用 std::shared_ptr
,即
template<typename T>
class Container
{
public:
// The pointer you get must be managed as well
Container(std::shared_ptr<T> e) : element(e) {}
std::shared_ptr<T> element;
};
那将是绝对安全的。实际上,如果对象超出创建它的代码的范围,您仍然有一个有效的指针,直到容器本身超出范围。如果 std::shared_ptr
的语义不完全适合您的情况,您可以进一步调整 std::weak_ptr
或 std::unique_ptr
的内存所有权关系。
你绝对应该研究一下 std::weak_ptr
,因为它允许你禁止某些代码获取指针的所有权,但仍然允许访问 if 指针有效在您需要访问它的位置。它还可以防止内存保留周期,因为 std::weak_ptr
不拥有内存。