如果不使用C++中的构造函数,我应该如何将值(而不是指针)强制转换为子类
How should I cast a value (not a pointer) to a subclass without using a constructor in C++?
我有以下类打算用作值类型(因为它们只存储一个整数):
class _foo_t
{
friend _foo_t _make_foo();
private:
int foo;
_foo_t(int foo) : foo(foo) {}
protected:
void *getptr() const; // defined in .cpp
};
template <typename T>
class foo_t : public _foo_t
{
public:
T *getptr() const { return (T*)_foo_t::getptr(); }
T &getref() const { return *(T*)_foo_t::getptr(); }
};
_foo_t _make_foo(); // defined in .cpp
template <typename T>
foo_t<T> make_foo()
{
return _make_foo(); // What kind of cast do I need here?
}
类foo_t<T>
只是_foo_t
的包装器,为getptr
和getref
成员函数提供类型安全性。同样,函数make_foo()
只是_make_foo<T>()
的一个包装器。由于foo_t<T>
是_foo_t
的子类,不添加任何字段,也没有虚拟成员,因此foo_t<T>
对象在内存中看起来应该与_foo_t
对象完全相同,并且我不希望这里有构造函数调用的开销。如何将_make_foo()
的返回值从_foo_t
安全、合规地转换为foo_t<T>
而不产生任何开销?
编辑:
根据请求,以下是上面的一些示例用法:
class SomeObject { /* ... */ };
foo_t<SomeObject> obj = make_foo<SomeObject>();
new (obj.getptr()) SomeObject();
obj.getref().doSomething();
实际上,make_foo
必须采用一个大小参数或其他参数。
如何安全、兼容地将_make_foo()的返回值从_foo_t强制转换为foo_t而不产生任何开销?
您肯定无法安全地投射,因为您不知道向下投射是有效的。然而,在这种特殊情况下,由于我们的派生类型与基本类型的大小相同,您可以使用
template <typename T>
foo_t<T> make_foo()
{
return static_cast<foo_t<T>&>(_make_foo());
}
也就是说,虽然这在CRTP世界里是有意义的,但我不确定它在这里是否有意义。
您可以将类模板foo_t
泛化为能够容纳任何数据类型,而不依赖于_foo_t
。你可以使用:
template <typename T> class foo_t
{
public:
char data[sizeof(T)];
T *getptr() const { return (T*)data; }
T &getref() const { return *(T*)data; }
};
template <typename T>
foo_t<T> make_foo()
{
return foo_t<T>();
}
下面是一个演示其用法的示例程序:
#include <iostream>
#include <new>
template <typename T> class foo_t
{
public:
char data[sizeof(T)];
T *getptr() const { return (T*)data; }
T &getref() const { return *(T*)data; }
};
template <typename T>
foo_t<T> make_foo()
{
return foo_t<T>();
}
struct Object1
{
int a;
int b;
};
struct Object2
{
int a;
double b;
};
struct Object3
{
double a;
double b;
};
int main()
{
foo_t<Object1> obj1 = make_foo<Object1>();
new (obj1.getptr()) Object1();
obj1.getref().a = 10;
obj1.getref().b = 20;
std::cout << "Object1 - a:" << obj1.getref().a << ", b: " << obj1.getref().b << std::endl;
foo_t<Object2> obj2 = make_foo<Object2>();
new (obj2.getptr()) Object2();
obj2.getref().a = 10;
obj2.getref().b = 20.35;
std::cout << "Object2 - a:" << obj2.getref().a << ", b: " << obj2.getref().b << std::endl;
foo_t<Object3> obj3 = make_foo<Object3>();
new (obj3.getptr()) Object3();
obj3.getref().a = 10.92;
obj3.getref().b = 20.35;
std::cout << "Object3 - a:" << obj3.getref().a << ", b: " << obj3.getref().b << std::endl;
return 0;
}
程序输出:
对象1-a:10,b:20对象2-a:10,b:2.35对象3-a:10.92,b:2.35
更新
鉴于您的评论,我认为您所需要的只是:
template <typename T>
class foo_t : public _foo_t
{
public:
// Make sure you can use all of the base class
// constructors in this class.
using _foo_t::_foo_t;
T *getptr() const { return (T*)_foo_t::getptr(); }
T &getref() const { return *(T*)_foo_t::getptr(); }
};
template <typename T>
foo_t<T> make_foo()
{
// Construct a foo_t<T> using a _foo_t and return it.
return foo_t<T>(_make_foo());
}
相关文章:
- 通过指向指针数组的指针访问子类的属性
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- 将C++子类成员函数(虚拟实现)传递给 C 类型函数指针
- 为什么带有指针子对象的文字类类型的 constexpr 表达式不能是非类型模板参数
- 为什么使用父指针指向子类?
- C++通过基类指针提升子类的序列化
- 如果指针的子类的方法对于子类是唯一的,如何访问这些方法?
- C++基类指针调用子虚函数,为什么基类指针可以看到子类成员
- 为什么指向基类的指针可以指向子类的对象?
- C++ 使用正确的子类指针
- 如何在 BaseClass 指针数组中存储指向子类对象的指针?
- 带有基类指针的强制转换向量,指向子类
- 跨子类的共享指针
- 无法将参数 3 从 'const QGraphicsItem *' 转换为 'const QObject *',这是指针,对象是 QGraphicsObject 的子类
- 如何从其抽象母类上的指针初始化子类?
- 可以将指向子类的指针分配给Varibale的超级类型
- 声明基类类型的指针,但随后通过指向子类来实例化它.这是良好的编程实践吗?
- C++ - 如何使用基指针重写子类方法
- 指向子类对象的指针的静态数组出现问题
- Arduino:指针子类的继承和数组