我在编写接受主类或子类参数的函数(使用函数重载)时会发现,通常会发生隐式向上转换(子类被升级为主类,而主类函数被调用)。我不希望发生这种隐式的向上转换,因为这意味着潜在的细微漏洞并在以后引起问题。
我在google上搜索过有关此信息的信息,但我可以使用的信息很少,只能间接引用它。
如何禁用,停止或阻止隐式向上转播(甚至是向下转发)?
(我无法提供任何示例代码,因为这是一个不时发生的一般问题。)
不,这与方法(我会指定方法)无关,而是函数。
没有示例代码,但伪想法: void Function(BaseClass& A); void Function(SubclassClass& B);
Function(ASubclass); //Implicit upcasting occurs, calls BaseClass instead
上述情况不会按常规发生(比如SubclassClass函数被淘汰/删除),但Subclass将被上传到BaseClass以与BaseClass函数一起使用,而不是报告错误或生成警告 - 要么会有所帮助,因为我不希望隐式向上转发。
请不要将upcasting与非虚方法调用混淆。
答案 0 :(得分:6)
class Base
{
};
class Derived1:public Base
{
};
class Derived2:private Base
{
};
void doSomething(Base *ptr)
{
}
int main()
{
Derived1 *ptr1 = new Derived1;
Derived2 *ptr2 = new Derived2;
doSomething(ptr1); //works fine
doSomething(ptr2); //Gives error
return 0;
};
向上转发:
只要派生类是从Base类派生的publically
,基类指针始终可以指向派生类对象。例如:第一个函数调用。
这种向上发生隐式。
如果派生是private
,则这种向上转换不会隐式发生,编译器会发出错误。
但是,使用private
继承并不是实现此行为的方法。如果它适合您的设计,您应该使用私有继承,它将隐含地保证您不会隐含地进行向上转换。
答案 1 :(得分:1)
你所谈论的“提升”是正常的。您描述的症状听起来像是在超载非虚拟父母成员函数。
例如
#include <iostream>
using namespace std;
struct A
{
void sayHello() {cout << "hello from A" << endl;}
};
struct B : public A
{
void sayHello() {cout << "hello from B" << endl;}
};
void hello(A& a)
{
a.sayHello();
}
int main()
{
A a;
B b;
hello(a);
hello(b);
}
将产生
hello from A
hello from A
但是如果你将virual添加到A :: sayHello,一切都会按预期工作
struct A
{
virtual void sayHello() {cout << "hello from A" << endl;}
};
答案 2 :(得分:0)
我不是100%确定发生了什么,但是如果在向具有基类参数类型的方法提供派生类对象时调用基类方法,则a)你没有覆盖派生类中的基类方法,或者更有可能b)您忘记了基类声明中的'virtual'关键字。否则,将按预期调用derived-class方法。
答案 3 :(得分:0)
@Als如果派生处于受保护模式,则您的示例将无法工作。仅在派生类中(在派生类的方法内)允许隐式向上转换,因为受保护的成员只能在派生的类或基类中访问。 / p>