簡體   English   中英

重載功能(虛擬/非虛擬)

[英]Overloaded functions(virtual/non virtual)

我有4個重載函數vfoo (3個是virtual)

我試圖在這里測試一些概念:

  1. 使用虛函數重載
  2. 當派生類實現了自己的重載函數版本時,重載函數將隱藏在派生類中。
  3. 基類指針存儲派生類對象時的行為是什么
  4. 派生類中的重載函數,例如void vfoo(char x)
#include<iostream>
using namespace std;

/*Base class having 4 overloaded function*/  
class ClassBaseV 
{
    public:

        virtual void vfoo( int x ) {
                cout << "ClassBaseV vfoo(int), x = " << x << endl;
        }

        virtual void vfoo( double x ) {
                cout << "ClassBaseV vfoo(double), x = " << x << endl;
        }

        virtual void vfoo( int x, double y ) {
                cout << "ClassBaseV vfoo(int,double), x = " << x << ", y = " << y << endl;
        }

        void vfoo( double x, int y ) {
                cout << "ClassBaseV vfoo(double,int), x = " << x << ", y = " << y << endl;
        }
};


class ClassDerived1 : public ClassBaseV 
{
    public:

        //Overloaded with char x
        void vfoo( char x ) {
                cout << "ClassDerived1 vfoo(char), x = " << x << endl;
        }


         //over riding int x
         void vfoo( int x ) {
                cout << "ClassDerived1 vfoo(int), x = " << x << endl;
        }


};


int main()
{
    ClassBaseV *cB = new ClassDerived1(); /*Base pointer storing derived class object*/
    ClassDerived1 *cd1 = new ClassDerived1(); //Derived class object  
    cd1->vfoo('a');//Direct call using derived class object. this works
    char a = 'a';
    cB->vfoo(a);   // trying to call char x using cB. This calls derived class int How?
    cB->vfoo(10);  // trying to call int x using CB. This calls derived class int 
    cB->vfoo(2.2); // Wanted this to not to work as base class overloaded functions are hidden but this works

    return 1;
}

第一個問題:

cB->vfoo(a);

當您在此處調用vfoo時,它將嘗試在ClassBaseV中找到vfoo(char x)的定義,但是沒有找到,但是仍然找到可以隱式轉換為的vfoo(int x)的定義,因此它將調用此方法。從ClassBaseV。

編譯器將嘗試獲取作為類型提供的類的方法的定義。

ClassBaseV *cB = new ClassDerived1();

在此行上,鍵入cB作為指向ClassBaseV的指針。 從現在開始,編譯器不能在子類中查找方法定義的缺點,但是仍然可以這樣做,因為ClassBaseV知道對父類的任何可能的繼承。

第二個問題:

cB->vfoo(2.2);

在這行上,您調用方法vfoo(double x),因為ClassBaseV中提供了對double的轉換,並且您沒有在ClassDerived1中覆蓋此方法。

因此,通常調用該方法的ClassBaseV實現。

如果要調用ClassDerived1中重寫的vfoo之一,則必須將其強制轉換為int或char(以及寬松的信息)

cB->vfoo(static_cast<int>(2.2));

或在ClassDerived1中添加一個新方法,以覆蓋ClassBaseV中的vfoo(double x)。

另外,如果要強制ClassDerived1實現ClassBaseV中的方法vfoo(double x),則必須將其聲明為純virtual:

virtual void vfoo( double x ) = 0;

如果您在派生類中重寫一部分重載,通常的做法是using聲明將所有未重寫的函數放到作用域中。 防止尷尬的失敗。

cB->vfoo(a);   // trying to call char x using cB. This calls derived class int How?

Base中的重載分辨率最接近匹配(char-> int)並使用虛擬調度進行調用

cB->vfoo(10);  // trying to call int x using CB. This calls derived class int 

在ovrload解析中進行匹配匹配並派生虛擬分派。

cB->vfoo(2.2); // Wanted this to not to work as base class overloaded functions are hidden but

精確匹配重載解決方案,虛擬派發至基地。

切勿嘗試刪除派生類中的功能。

接口繼承意味着:我最多需要保證基本需求,並且我的行為符合基本合同。

“當基類指針存儲派生類對象時的行為是什么” -這是多態性的核心思想。 多態性基於特定的行為,該行為基於運行時確定的對象類型,而重載函數則在編譯時解決。

常量文字的類型可以很容易地在編譯時確定10int2.2double ,這將確定將使用哪個成員函數。 然后,實例的類型將確定將使用哪個實現(哪個類)。 這是更簡單的示例:

class Animal {
public:
    virtual void makeSound(){ std::cout << "hi" << std::endl; }
    virtual void makeSound(int pain){ std::cout << "ouch" << std::endl; }
    virtual void makeSound(double d){ std::cout << "aaaaaaaargh" << std::endl; }
};

class Cat : public Animal {
public:
    virtual void makeSound(){ std::cout << "meow" << std::endl; }
    virtual void makeSound(int pain){ std::cout << "MEEEEEOW!!!" << std::endl; }
    virtual void makeSound(double d){ std::cout << "meow double" << std::endl; }
};

int main() {
    Animal *a = new Animal();
    Animal *cat = new Cat();
    a->makeSound();
    cat->makeSound();
    a->makeSound(100);
    cat->makeSound(100);
    cat->makeSound(750.80);
}

輸出:

你好

哎喲
EE !!!
喵喵

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM