成员变量多态性

时间:2019-01-19 12:13:43

标签: c++ polymorphism

我从C ++开始,我很难使用多态性,尤其是当我想在新类的构造函数中使用它时。我知道该问题已得到here的处理,但我不明白,我的情况也有所不同。

要了解如何使用它,我构建了这个小程序。这是main.cpp

#include <iostream>
#include <string>
#include <headers.h>
using namespace std;

void Display(Car &c)
{
    c.Show();
}

int main()
{
    Car Clio(50);
    SportCar Ferrari(200,200);
    Clio.Show();
    Ferrari.Show();

    Display(Ferrari);

    Race(Ferrari, Track());

    return 0;
}

headers.h文件:

#ifndef CAR_H
#define CAR_H

class Car
{
    public:
        Car(double s);
        Car();
        virtual void Show() const;

    protected:
        double m_Speed;

    private:
};

#endif // CAR_H


#ifndef SPORTCAR_H
#define SPORTCAR_H

class SportCar : public Car
{
    public:
        SportCar(double s, double p);
        SportCar();
        virtual void Show() const;

    protected:

    private:
        double m_Price;
};

#endif // SPORTCAR_H


#ifndef TRACK_H
#define SPORTCAR_H

class Track
{
    public:
        Track(double l);
        Track();

    protected:

    private:
        double m_Length;
};

#endif // SPORTCAR_H

#ifndef RACE_H
#define RACE_H


class Race
{
    public:
        Race(const Car& , Track t);

    protected:
        Car &m_Car;
        Track m_Track;

    private:
};

#endif // RACE_H

最后,src.cpp文件:

#include <string>
#include <iostream>
#include <headers.h>
using namespace std;

Car::Car(double s)
{
     m_Speed = s;
}

Car::Car()
{
    m_Speed = 50;
}

void Car::Show() const
{
    cout << "I'm a car" << endl;
}

SportCar::SportCar(double s, double p) : Car(s)
{
    m_Price = p;
}

SportCar::SportCar() : Car()
{
    m_Price = 200;
}

void SportCar::Show() const
{
    cout << "I'm a sportcar" << endl;
}

Track::Track(double l)
{
    m_Length = l;
}

Track::Track()
{
    m_Length = 10;
}

Race::Race(const Car& c, Track t)
{
    m_Car = c;
    m_Track = t;
    m_Car.Show();
}

总而言之,我有两种不同的汽车类别,其中一种(SportCart)继承自另一种(Car),具有两种不同的Show()方法。我有一个Race类,其成员是一种汽车和一个Track。当我使用Race构造函数时,无法将汽车作为SportCar传递参数。

结果我有:

I'm a car
I'm a sportcar
I'm a sportcar
I'm a car

我想要:

I'm a car
I'm a sportcar
I'm a sportcar
I'm a sportcar

我尝试使用类似的引用:

protected:
    Car &m_Car;
    Track m_Track;

但是它也不起作用,我遇到了无法修复的错误:

||=== Build: Debug in test (compiler: GNU GCC Compiler) ===|
E:\documents\c++\test\src\src.cpp||In constructor 'Race::Race(const Car&, Track)':|
E:\documents\c++\test\src\src.cpp|46|error: uninitialized reference member in 'class Car&' [-fpermissive]|
include\headers.h|66|note: 'Car& Race::m_Car' should be initialized|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

谢谢您的帮助。

2 个答案:

答案 0 :(得分:2)

请注意,在C ++中,“初始化”(以某种方式创建对象,如std::string str = "hi";)和“赋值”(更改现有对象的值,例如str = "hi";)是两个不同的东西。

当您编写类似的构造函数时

Car::Car(double s)
{
     m_Speed = s;
}

C ++需要对象及其所有成员存在,因此在您到达第一个{时已经被初始化了。语句m_Speed = s;是赋值,而不是初始化。由于您未指定m_Speed的初始化方式,因此C ++在构造函数主体开始之前会插入逻辑以对其进行“默认初始化”(尽管对于double这样的基本类型,这仅意味着它具有一个不确定的值,直到分配为止。

这通常与类型double的成员无关。但是它可以用于类类型的成员,也可以肯定地用于引用类型的成员:引用必须被初始化,因为引用必须始终引用某个对象,而赋值的左侧总是引用变量分配给该引用对象;无法更改引用所引用的对象。

指定构造函数如何初始化成员的方法是使用成员初始化列表:

Car::Car(double s)
    : m_Speed(s)
{}

Race::Race(const Car& c, Track t)
    : m_Car(c), m_Track(t)
{
    m_Car.Show();
}

尽可能使用成员初始化器列表是一个好习惯,但是在这里您遇到了绝对需要它的情况。

[注1:上面显示的Race构造函数由于另一个问题仍然无法正常工作:您无法从Car&初始化const Car&引用。您需要将构造函数更改为采用非const参数,或者将成员更改为具有类型const Car&。非const参数也可以避免绑定到临时文件的潜在问题。]

[注2:为类成员指定初始化程序的另一种方法是将= something;放在类内的成员声明之后。当构造函数未为该成员指定初始化程序时,将在隐式定义的默认构造函数(如果有)中使用此默认初始化程序。当您希望多个构造函数使用相同的初始化程序时,这会很方便。]

答案 1 :(得分:1)

问题在于,必须在错误消息指出时初始化引用。为此,我们使用initializer list

Race::Race(Car& c, Track t) : m_Car(c), m_Track(t)
{
    m_Car.Show();
}

编辑:m_Track不需要在这里初始化,但是,如果可能的话,始终使用初始化器列表是一种很好的做法,而且效率更高。