【发布时间】:2020-04-06 06:27:20
【问题描述】:
我正在学习 C++,在我老师的课程中,他解释说多态性与按值传递不兼容。
他解释说,当您将对象按值传递给方法时,编译器会在堆栈中生成对象的副本,出于优化原因,他选择创建父类类型的副本。
例如,假设我有一个名为 A 的类,而 B 类是 A 的子类。 如果我按值传递 B 类型的对象,编译器会在堆栈上创建它的副本,但类型为 A。
我的问题是:
总是这样吗?
假设我为 B 类创建了一个复制构造函数,那么当我将 B 类型的对象按值传递给方法时,编译器是否会使用它?还是它仍然将 B 复制为 A(对象切片)?如果不是,为什么?
谢谢!
编辑:示例
// in headers file
// for A
class A
{
public :
virtual void Display() const
{ cout << "A::Display() was called << endl; }
};
// for B
class B : public A
{
public :
void Display() const
{ cout << "B::Display() was called << endl; }
};
现在在另一个名为 main.cpp 的文件中有 3 种可能的情况:
案例 1:
void f( const A & anA)
{
anA.Display();
}
int main()
{
B anB;
f (anB);
return 0;
}
案例 2:
void f( const A * anA)
{
anA->Display();
}
int main()
{
A * anB = new B;
f ( anB );
return 0;
}
案例 3:
void f( A anA)
{
anA.Display();
}
int main()
{
B anB;
f ( anB );
return 0;
}
据我了解,案例 1 和案例 2 将显示所需的输出(意思是“B::Display() 被调用”),而案例 3 不会(它将输出:“A::Display () 被调用”),即使 Display 方法在 A 类中被指定为虚拟方法。
【问题讨论】:
-
这能回答你的问题吗? What is object slicing?
-
@RichardCritten 谢谢。它肯定使对象切片更容易理解。但是,在将对象(在继承的上下文中)通过值传递给方法时,我仍然对编译器优化感到困惑到方法。
-
请为您的问题添加minimal reproducible example,这样我确信我明白您在问什么。
-
对象切片是当你将一些多态对象传递给函数时发生的事情的答案。您不需要为此进行优化即可出错
-
发生切片并不是一种优化:只是在 C++ 中声明为这样的对象(而不是指针或引用)总是具有完全指定的类型。
标签: c++ object inheritance compiler-optimization pass-by-value