Helpex - Trao đổi & giúp đỡ Đăng nhập
357

Giả sử tôi có các lớp học FooBarthiết lập như thế này:

class Foo
{
public:
    int x;

    virtual void printStuff()
    {
        std::cout << x << std::endl;
    }
};

class Bar : public Foo
{
public:
    int y;

    void printStuff()
    {
        // I would like to call Foo.printStuff() here...
        std::cout << y << std::endl;
    }
};

Như được chú thích trong mã, tôi muốn có thể gọi hàm của lớp cơ sở mà tôi đang ghi đè. Trong Java có super.funcname()cú pháp. Điều này có khả thi trong C ++ không?

357 hữu ích 2 bình luận 256k xem chia sẻ
477

Cú pháp C ++ như sau:

class Bar : public Foo {
  // ...

  void printStuff() {
    Foo::printStuff(); // calls base class' function
  }
};
477 hữu ích 5 bình luận chia sẻ
125

Đúng,

class Bar : public Foo
{
    ...

    void printStuff()
    {
        Foo::printStuff();
    }
};

Nó giống như supertrong Java, ngoại trừ nó cho phép gọi các triển khai từ các cơ sở khác nhau khi bạn có đa kế thừa.

class Foo {
public:
    virtual void foo() {
        ...
    }
};

class Baz {
public:
    virtual void foo() {
        ...
    }
};

class Bar : public Foo, public Baz {
public:
    virtual void foo() {
        // Choose one, or even call both if you need to.
        Foo::foo();
        Baz::foo();
    }
};
125 hữu ích 2 bình luận chia sẻ
71

Đôi khi bạn cần gọi triển khai của lớp cơ sở, khi bạn không ở trong hàm dẫn xuất ... Nó vẫn hoạt động:

struct Base
{
    virtual int Foo()
    {
        return -1;
    }
};

struct Derived : public Base
{
    virtual int Foo()
    {
        return -2;
    }
};

int main(int argc, char* argv[])
{
    Base *x = new Derived;

    ASSERT(-2 == x->Foo());

    //syntax is trippy but it works
    ASSERT(-1 == x->Base::Foo());

    return 0;
}
71 hữu ích 1 bình luận chia sẻ
28

Chỉ trong trường hợp bạn làm điều này cho nhiều hàm trong lớp của mình:

class Foo {
public:
  virtual void f1() {
    // ...
  }
  virtual void f2() {
    // ...
  }
  //...
};

class Bar : public Foo {
private:
  typedef Foo super;
public:
  void f1() {
    super::f1();
  }
};

Điều này có thể tiết kiệm một chút văn bản nếu bạn muốn đổi tên Foo.

28 hữu ích 2 bình luận chia sẻ
6

Nếu bạn muốn gọi một hàm của lớp cơ sở từ lớp dẫn xuất của nó, bạn có thể chỉ cần gọi bên trong hàm được ghi đè bằng cách đề cập đến tên lớp cơ sở (như Foo :: printStuff () ).

mã ở đây

#include <iostream>
using namespace std;

class Foo
{
public:
    int x;

    virtual void printStuff()
    {
         cout<<"Base Foo printStuff called"<<endl;
    }
};

class Bar : public Foo
{
public:
    int y;

    void printStuff()
    {
        cout<<"derived Bar printStuff called"<<endl;
        Foo::printStuff();/////also called the base class method
    }
};

int main()
{
    Bar *b=new Bar;
    b->printStuff();
}

Một lần nữa, bạn có thể xác định trong thời gian chạy hàm nào sẽ gọi bằng đối tượng của lớp đó (dẫn xuất hoặc cơ sở). Nhưng điều này yêu cầu hàm của bạn ở lớp cơ sở phải được đánh dấu là ảo.

mã bên dưới

#include <iostream>
using namespace std;

class Foo
{
public:
    int x;

    virtual void printStuff()
    {
         cout<<"Base Foo printStuff called"<<endl;
    }
};

class Bar : public Foo
{
public:
    int y;

    void printStuff()
    {
        cout<<"derived Bar printStuff called"<<endl;
    }
};

int main()
{

    Foo *foo=new Foo;
    foo->printStuff();/////this call the base function
    foo=new Bar;
    foo->printStuff();
}
6 hữu ích 0 bình luận chia sẻ
1

Nếu có nhiều mức kế thừa, bạn có thể chỉ định lớp cơ sở trực tiếp, ngay cả khi việc triển khai thực tế ở mức thấp hơn.

class Foo
{
public:
  virtual void DoStuff ()
  {
  }
};

class Bar : public Foo
{
};

class Baz : public Bar
{
public:
  void DoStuff ()
  {
    Bar::DoStuff() ;
  }
};

Trong ví dụ này, lớp Baz chỉ định Bar :: DoStuff () mặc dù Thanh lớp không chứa phần triển khai của DoStuff . Đó là một chi tiết, mà Baz không cần biết.

Rõ ràng là cách gọi Bar :: DoStuff tốt hơn Foo :: DoStuff , trong trường hợp phiên bản Bar sau này cũng ghi đè phương thức này.

1 hữu ích 0 bình luận chia sẻ
0

kiểm tra điều này...

#include <stdio.h>

class Base {
public:
   virtual void gogo(int a) { printf(" Base :: gogo (int) \n"); };    
   virtual void gogo1(int a) { printf(" Base :: gogo1 (int) \n"); };
   void gogo2(int a) { printf(" Base :: gogo2 (int) \n"); };    
   void gogo3(int a) { printf(" Base :: gogo3 (int) \n"); };
};

class Derived : protected Base {
public:
   virtual void gogo(int a) { printf(" Derived :: gogo (int) \n"); };
   void gogo1(int a) { printf(" Derived :: gogo1 (int) \n"); };
   virtual void gogo2(int a) { printf(" Derived :: gogo2 (int) \n"); };
   void gogo3(int a) { printf(" Derived :: gogo3 (int) \n"); };       
};

int main() {
   std::cout << "Derived" << std::endl;
   auto obj = new Derived ;
   obj->gogo(7);
   obj->gogo1(7);
   obj->gogo2(7);
   obj->gogo3(7);
   std::cout << "Base" << std::endl;
   auto base = (Base*)obj;
   base->gogo(7);
   base->gogo1(7);
   base->gogo2(7);
   base->gogo3(7);

   std::string s;
   std::cout << "press any key to exit" << std::endl;
   std::cin >> s;
   return 0;
}

đầu ra

Derived
 Derived :: gogo (int)
 Derived :: gogo1 (int)
 Derived :: gogo2 (int)
 Derived :: gogo3 (int)
Base
 Derived :: gogo (int)
 Derived :: gogo1 (int)
 Base :: gogo2 (int)
 Base :: gogo3 (int)
press any key to exit

cách tốt nhất là sử dụng hàm base :: như nói @sth

0 hữu ích 2 bình luận chia sẻ
0

Có bạn có thể gọi nó. Cú pháp C ++ để gọi hàm lớp cha trong lớp con là

class child: public parent {
  // ...

  void methodName() {
    parent::methodName(); // calls Parent class' function
  }
};

Đọc thêm về ghi đè hàm .

0 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ c++ virtual-functions overriding , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading