c++:通过基类接口构造派生对象
c++: Construct derived object via base class interface
我有一个模板类,它是由两个参数构造的,一个整数和该类的前一个实例。我希望能够将这些类的实例存储在容器中,这就是为什么我让它从基类继承(请忽略非智能指针):
class base {
virtual base* getNext(unsigned x) = 0;
};
template <class D>
class derived :
public base {
/* no memory allocation here, simply changes the data in next */
void construct_impl(unsigned x, const derived<D>& previous, derived<D>& next);
derived(); /* default constructor */
derived(unsigned x, const derived<D>& previous) { /* construct from previous object */
allocate_memory_for_this();
construct_impl(x, previous, *this);
}
base* getNext(unsigned x) {
return new derived(x, *this);
}
};
现在我想在 base
类中创建一个函数,它将以与construct_impl
相同的方式构造一个derived<D>
对象,即不重新分配内存。我在想这样的事情
class base {
virtual base* getNext(unsigned x) = 0;
virtual void getNext_noalloc(unsigned x, base* already_allocated_derived_object) = 0;
}
它将像这样在派生类中被覆盖
void getNext_noalloc(unsigned x, base* already_allocated_derived_object) {
construct_impl(x, *this, *already_allocated_derived_object);
}
不幸的是,由于没有从base*
到derived<D>*
的转换,因此无法编译(除非我使用static_cast)。有什么方法可以实现我需要的吗?提前感谢!
David Nehme 在评论中链接到的奇怪重复出现的模板模式可能会满足您的需求。它不应该阻止您将派生类的对象一起存储在同一个容器中。看起来您确实正在实现一个双向链表,并从给定的项自动创建下一个项目。(这将使从该元素到末尾的列表无效,除非它是尾部。
我相信(我还没有尝试过)你应该在覆盖中测试一个dynamic_cast<>
,以便getNext_noalloc()
测试next
指针并调用匹配类的construct_impl()
。
// override in derived class
void getNext_noalloc(unsigned x, base* already_allocated_derived_object) {
derived<D1>* p1 = dynamic_cast< derived<D1> >(already_allocated_derived_object);
derived<D2>* p2 = dynamic_cast< derived<D2> >(already_allocated_derived_object);
if(p1 != NULL) {
p1->construct_impl(x, *this, *p1); // 2nd parameter should take base type
} else if(p2 != NULL) {
p2->construct_impl(x, *this, *p2); // 2nd parameter should take base type
}
}
这确实假定这两个类相互了解,因此您必须在声明类之后具有函数定义,如果construct_impl()
是私有的或受保护的,则这些类必须friend
。
使用 dynamic_cast<>()
应该意味着您根本不需要 CRTP,但您必须检查每个强制转换以确保它转换为正确的类型。
将指针从基类型转换为子类型
你可能在误解C++
写作时感到困惑。class ClownCar {
unsigned int x;
ClownCar inner_car;
};
但这是不可能的!sizeof(ClownCar)
会是什么?它必须至少是 sizeof x + sizeof inner_car
;即sizeof(unsigned int) + sizeof(ClownCar)
;即,至少比自身大四个字节。
因此,类不能包含其自己的类的实例。 继承,无论是虚拟的还是其他的,在这里都无关紧要。那我们该怎么办呢?我们使用指针!
class ClownCar {
unsigned int x;
ClownCar *inner_car;
public:
ClownCar() : x(0), inner_car(nullptr) {}
ClownCar(unsigned int x, ClownCar *previous) : x(x), inner_car(previous) {}
ClownCar *getNext(unsigned int x) {
return new ClownCar(x, this);
}
};
int main() {
ClownCar inmost_car;
ClownCar *car1 = inmost_car.getNext(42);
ClownCar *car2 = car1.getNext(43);
// ...
delete car2;
delete car1;
// of course we don't delete inmost_car, since it lives on the stack
}
当然,这不是很C++。我们可能想摆脱所有这些*
,并使每辆车"拥有"其内部汽车(并负责删除它)。我们可以使用标准库的std::unique_ptr
来表示这种"所有权"的概念(另请参阅如何将unique_ptr参数传递给构造函数或函数?...但实际上,我们在这里得到的只是一个单链的ClownCar
列表,这是STL免费提供给我们的:
struct ClownCar { unsigned int x; };
typedef std::list<ClownCar> ClownCarList; // ta-da!
所以我认为真正的问题是,你想完成什么?
- 为什么此派生对象无法访问基类的后递减方法?
- 如何在新的派生对象中获取基本对象的数据?
- 如何将成员函数作为参数传递并在派生对象上执行方法列表
- 在没有默认构造函数的情况下创建的派生对象
- OOP 标识派生对象
- 如何创建派生对象的向量?
- 将基类分配给派生对象,反之亦然,以C++以及静态和动态对象之间的差异
- 如何从 Gtk::窗口调用派生对象的析构函数
- 无法在派生对象上运行虚拟函数
- 尝试删除指向派生对象的基指针时断言错误
- 存储在一个通用容器中的派生对象.如何避免铸造
- 将派生对象分配给函数内的基类指针
- 替换派生对象向量中的对象"no matching function to call"
- 派生对象调用的 Base 方法的模板推导
- 用于填充 Base 和派生对象的 shared_ptr 向量的函数模板
- C++ UBSAN 对派生对象产生误报
- 如何验证我是否正在使用C++中的基对象或派生对象
- C++ 构造函数和派生对象
- 将派生对象传递给模板
- 指向派生作品的基本指针,即使派生对象不存在