Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从派生类对象调用基类方法_C++_Inheritance - Fatal编程技术网

C++ 从派生类对象调用基类方法

C++ 从派生类对象调用基类方法,c++,inheritance,C++,Inheritance,如何从派生类对象调用由派生类重写的基类方法 class Base{ public: void foo(){cout<<"base";} }; class Derived:public Base{ public: void foo(){cout<<"derived";} } int main(){ Derived bar; //call Base::foo() from bar here? return 0; } 类基{ 公众: v

如何从派生类对象调用由派生类重写的基类方法

class Base{
  public:
    void foo(){cout<<"base";}
};

class Derived:public Base{
  public:
    void foo(){cout<<"derived";}
}

int main(){
  Derived bar;
  //call Base::foo() from bar here?
  return 0;
}
类基{
公众:

void foo(){cout首先派生的应该从Base继承

 class Derived : public Base{
也就是说

首先,你们不能让foo处于派生状态

class Base{
  public:
    void foo(){cout<<"base";}
};

class Derived : public Base{

}

int main(){
  Derived bar;
  bar.foo() // calls Base::foo()
  return 0;
}
首先考虑将
foo()
虚拟化

class Base {
public:
    virtual ~Base() = default;

    virtual void foo() { … }
};

class Derived : public Base {
public:
    virtual void foo() override { … }
};
但是,这可以完成以下任务:

int main() {
    Derived bar;
    bar.Base::foo();
    return 0;
}
始终可以(*)使用限定id引用基类的函数:

Derived::bar
是隐式虚拟的,即使您不使用
virtual
关键字,只要它的签名与
Base::bar
兼容)

限定id的形式可以是
X::Y
,也可以是
::Y
前面的部分指定要在哪里查找标识符
Y
。在第一种形式中,我们查找
X
,然后从
X
的上下文中查找
Y
。在第二种形式中,我们查找
Y
在全局命名空间中

非限定id不包含
::
,因此不(自身)指定查找名称的上下文

在表达式
b->foo
中,
b
foo
都是非限定ID。
b
在当前上下文中查找(在上面的示例中是
main
函数)。我们找到局部变量
Base*b
。因为
b->foo
具有类成员访问的形式,我们从
b
(或者更确切地说是
*b
)类型的上下文中查找
foo
。因此我们从
Base
的上下文中查找
foo
。我们将找到成员函数
void foo()
Base
中声明,我将其称为
Base::foo

对于
foo
,我们现在完成了,并调用
Base::foo

对于
b->bar
,我们首先找到
Base::bar
,但它被声明为
virtual
。因为它是
virtual
,我们执行虚拟分派。这将调用对象类型的类层次结构中的最终函数重写器
b
指向。因为
b
指向
类型的对象>派生的
,最后的重写器是
派生的::bar

当从
Derived
的上下文中查找名称
foo
时,我们将找到
Derived::foo
。这就是为什么
Derived::foo
被称为隐藏
Base::foo
。表达式,例如
d.foo()
,或者在
Derived
的成员函数中,简单地使用
foo()
This->foo()
,将从
派生的上下文中查找

当使用限定id时,我们显式地声明查找名称的位置的上下文。表达式
Base::foo
表示我们希望从
Base
的上下文中查找名称
foo
(例如,它可以查找继承的
Base
函数).此外,它还禁用虚拟分派。

因此,
d.Base::foo()
将找到
Base::foo
并调用它;
d.Base::bar()
将找到
Base::bar
并调用它


有趣的事实:纯虚拟函数可以有一个实现。它们不能通过虚拟分派调用,因为它们需要被重写。但是,您仍然可以使用限定id调用它们的实现(如果它们有)

#包括
结构基{
虚拟void foo()=0;
};

void Base::foo()

在本例中,可以使用using关键字,也可以使用限定符。此外,请参阅

#包括
阶级基础{
公众:

void foo(bool-bOne,bool-bTwo){std::coutIt最好将其写成
bar.Base::foo()
@Mankarse,直到这成为可能。如果将foo()设为虚拟,仍然需要调用
bar.Base::foo()
访问基类方法,对吗?@XunYang是的,你可以。在这种情况下,虚拟性是不相关的,但我发现它值得一提。好的,谢谢!实际上我正在使用一组库,它们使用一个非常通用的函数名
void Base1::begin(){\\initialization}
类派生:public Base1,public Base2{…};void-Derived::begin(){\\initialization}
,所以体系结构很遗憾超出了我的能力范围:(我只是想在这里做一个黑客测试:)相关:如果它不是虚拟的,它就不会被覆盖,
Derived::foo
而是隐藏
Base::foo
@DyP谢谢你知道这很好:)这看起来很像一个设计问题。如果
Derived
有自己版本的
foo
,那么如果有人在类外调用我发现这个答案可能比接受的答案更有用。你的派生类foo隐藏了基类foo。在这种情况下使用限定符id语法也有效吗?@nurabha你能详细解释一下吗?我不太明白你的问题是什么。实际上,派生类foo并没有被派生类foo覆盖ss foo,但它是隐藏的。如果将基类指针指向派生对象并使用此指针调用foo,则将打印base。base*basePtrToDerived=&bar;basePtrToDerived->foo();@nurabha是的。强制转换到基是调用
base::foo
的另一种方法。使用限定id调用基类的函数时,不管派生类中该函数发生了什么,它都可以工作-它可以隐藏,可以重写,可以私有(通过使用Using声明),使用限定id时,您直接访问基类的函数。
class Base {
public:
    virtual ~Base() = default;

    virtual void foo() { … }
};

class Derived : public Base {
public:
    virtual void foo() override { … }
};
int main() {
    Derived bar;
    bar.Base::foo();
    return 0;
}
#include <iostream>

class Base{
  public:
    void foo(){std::cout<<"base";}
};

class Derived : public Base
{
  public:
    void foo(){std::cout<<"derived";}
};

int main()
{
  Derived bar;
  //call Base::foo() from bar here?
  bar.Base::foo(); // using a qualified-id
  return 0;
}
struct Base {
   void foo()         { std::cout << "Base::foo\n"; }
   virtual void bar() { std::cout << "Base::bar\n"; }
};

struct Derived : Base {
   void foo()         { std::cout << "Derived::foo\n"; }
   virtual void bar() { std::cout << "Derived::bar\n"; }
};

int main() {
    Derived d;
    Base* b = &d;
    b->foo(); // calls Base::foo
    b->bar(); // calls Derived::bar
}
#include <iostream>

struct Base {
    virtual void foo() = 0;
};

void Base::foo() { std::cout << "look ma, I'm pure virtual!\n"; }

struct Derived : Base {
    virtual void foo() { std::cout << "Derived::foo\n"; }
};

int main() {
    Derived d;
    d.foo();       // calls Derived::foo
    d.Base::foo(); // calls Base::foo
}
#include <iostream>

struct Base {
public:
    void public_fun() { std::cout << "Base::public_fun\n"; }
private:
    void private_fun() { std::cout << "Base::private_fun\n"; }
};

struct Public_derived : public Base {
public:
    void public_fun() { std::cout << "Public_derived::public_fun\n"; }
    void private_fun() { std::cout << "Public_derived::private_fun\n"; }
};

struct Private_derived : private Base {
public:
    void public_fun() { std::cout << "Private_derived::public_fun\n"; }
    void private_fun() { std::cout << "Private_derived::private_fun\n"; }
};

int main() {
    Public_derived p;
    p.public_fun();        // allowed, calls Public_derived::public_fun
    p.private_fun();       // allowed, calls Public_derived::public_fun
    p.Base::public_fun();  // allowed, calls Base::public_fun
    p.Base::private_fun(); // NOT allowed, tries to name Base::public_fun

    Private_derived r;
    r.Base::public_fun();  // NOT allowed, tries to call Base::public_fun
    r.Base::private_fun(); // NOT allowed, tries to name Base::private_fun
}
#include <iostream>

class Base{
  public:
    void foo(bool bOne, bool bTwo){std::cout<<"base"<<bOne<<bTwo;}
};

class Derived : public Base
{
  public:
    void foo(bool bOne){std::cout<<"derived"<<bOne;}
};

int main()
{
  Derived bar;
  //bar.foo(true,true);      // error:    derived func attempted
  bar.foo(true);             // no error: derived func
  bar.Base::foo(true,true);  // no error: base func, qualified
  return 0;
}