是否可以覆盖C ++子类中的函数而不使用虚拟关键字到父类的抽象函数?

时间:2012-03-08 15:24:42

标签: c++ visual-c++ override function-overriding

class Parent {
public:
    void func1(); // Complete meaningful definition in parent given.

    virtual HRESULT func2()=0;  // Bcoz of this function Parent class is abstract. 
};


class Child: public Parent {
public:
    void func1(); // Different definition in child.
};

这在C ++中是否可行?我重写了func1()这不是虚拟的,它已经在父抽象类中有了一个定义。

5 个答案:

答案 0 :(得分:20)

[假设此处Child扩展Parent,与代码快照显示的内容不同

是的,有可能[它被称为隐藏] - 但你不会得到dynamic dispatch行为。

静态类型将定义将调用哪个方法,而不是动态类型。

例如:

Parent* p = new Child;
p->func1();

将调用Parent::func1()
而:

Child* c = new Child;
c->func1();

将调用Child::func1()

答案 1 :(得分:5)

不,实际上覆盖父级中的定义是不可能的(至少在谈论C ++时,“覆盖”通常专门用于引用虚函数)。相反,在子类中定义具有相同名称的函数只需隐藏具有相同名称的父级中的函数(即,在子对象的上下文中,查找该名称只会查找孩子的功能,而不是父母的功能。)

如果你想(并且函数有不同的签名),你也可以获得父和子被视为重载的函数,因此调用将尝试更好地调用任何匹配:

struct parent {
    void func1(char) {}
};

struct child : public parent { 
    void func1(long) { }

    using parent::func1;
};

现在,你得到:

child c;
c.func1('a'); // calls parent::func1
c.func1(123L); // calls child::func1

这仍然是第三种类型的行为,不同于虚拟函数在子项中具有隐藏父项中的函数。

使用虚函数,调用哪个函数的选择基于动态类型,因此如果您有一个指向基类的指针/引用,则调用的函数取决于它是引用基类的对象还是衍生类。

当你隐藏函数时,被调用的函数是基于静态类型的,所以如果你通过对base的指针/引用来调用它,它会调用基函数,即使它实际上是指一个对象。派生类。但是,如果您使用指针或引用(或直接使用派生类的实例),它将调用派生类中的函数。

使用using语句,您将获得函数重载,因此当您调用函数时(在派生类的上下文中),被调用的函数基于哪个函数的签名是参数的最佳匹配(你通过了。

答案 2 :(得分:2)

如果它们具有不同的参数类型,您可以重载

您可以隐藏,在此处显示的意义上,以便在知道它正在查看子实例的代码中调用Child::func1而不是Parent::func1。但是,正如amit指出的那样,你没有得到动态调度。


struct StaticParent {
  void foo();
};
struct StaticChild : public StaticParent {
  void foo();
}

StaticChild sc;
sc.foo(); // calls StaticChild::foo

StaticParent &sp = sc;
sp.foo(); // calls StaticParent::foo

struct VirtualParent {
  virtual void foo();
};
struct VirtualChild : public VirtualParent {
  virtual void foo();
}

VirtualChild vc;
vc.foo(); // calls VirtualChild::foo

VirtualParent &vp = vc;
vp.foo(); // calls VirtualChild::foo

答案 3 :(得分:0)

是的,这是有效的C ++语法,并将定义一个Child :: func1,它在Child中隐藏Parent :: func1。

但是,这并不意味着它完全取代了Child :: Parent :: func1。仍然可以在子元素上显式调用此函数。

Child c;
c.Parent::func1();

此外,此功能是虚拟的。因此,以下..

Child c;
Parent& p = c;
p.func1();

将调用Parent :: func1而不是Child :: func1。

答案 4 :(得分:0)

大多数人都说过了。

如果你谈论java,你的期望是正确的。在java中,可以覆盖任何非私有的非final方法。也许您比C ++更熟悉其他编程语言

顺便说一句,你的代码中有两件事是错误的

  • ”必须写成小写
  • 班级成员的默认访问权限为“私有”。覆盖非纯粹的
  • 私有成员是不允许也没有用的