如何在考虑对象切片的同时通过传入单个 Base 对象来打印出数组中的对象?

How to print out objects in an array by passing in a single Base object while accounting for object slicing?

本文关键字:对象 Base 单个 打印 数组 切片      更新时间:2023-10-16

假设我有这样的东西:

int main()
{
Base *array[2];
array[0] = new Base("Hello", 2);
array[1] = new Derived("Bye", 3, 5);
DisplayEverything(array[0]);
DisplayEverything(array[1]);
cout << endl << "Deleting...." << endl << endl;
for (int i = 0; i < 2; i++) {
delete array[i];
}
}

以及打印 Base 和 Derived 对象的非成员函数:

void DisplayEverything(Base* a)
{
a->print();
}

在 Base 和 Derived 类中,我设置了一个虚拟析构函数和一个虚拟打印函数,例如:虚拟 void print();

void Base::print()
{
cout << a << " " << b << endl;
}

和:

void Derived::print()
{
cout << get_a() << " " << get_b() << " " << c << endl;
}

这将完成预期的事情,但是有什么方法可以传递对象而不是指针吗?我希望函数是这样的:

void DisplayEverything (Base a)
{   
a.print();
}

我该怎么做这样的事情?

我不确定为什么这是不可能的,因为我已经做过一次了,但我遇到了对象切片问题,这是我遇到的:

Base *array;
array = new Base [2]; 
array[0].set_info("Hi", 1, 2); 
DisplayEverything(array[0]); 

现在,DisplayEverything 函数如下所示:

void DisplayEverything (Base a) 
{ 
a.print(); 
} 

首先,一些准则:

  1. 不要使用原始指针进行内存管理。使用智能指针,例如std::unique_ptr。在现代C++new中,delete几乎不应该出现在源代码中。

  2. 不要使用继承,除非您有一个共享同一接口的事物的清晰可扩展层次结构。std::variant可能更适合您的用例(并且具有价值语义)。

  3. 不要使用 C 样式数组,最好从<array>标头中std::array


有什么方法可以传递对象而不是指针吗?

如果您希望在运行时通过多态继承进行虚拟调度,答案是否定的。您需要传递指针(如果拥有,则std::unique_ptr)或引用。

如果您希望在编译时进行调度,可以使用模板:

template <typename T>
void DisplayEverything (T a)
{   
a.print();
}

或者,如果要对一组封闭的类型使用值语义进行运行时调度,请使用std::variant