Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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++_Oop_Derived Class - Fatal编程技术网

C++ 将属性传递给基类的机制

C++ 将属性传递给基类的机制,c++,oop,derived-class,C++,Oop,Derived Class,将属性从派生类传递到基类的机制是什么,以便: 基本用户可以访问它们 它们可以很容易地存储在STL容器中 外部的任何人都只能在派生类上访问它们 有效性不是很有价值 属性是一个与派生类的每个对象相关的常量。可以虚拟执行,也可以非虚拟执行。但要回答其中哪一个是最好的,让我们检查一下您的示例: class自行车:公共车辆 { 公众: 自行车(可行驶车辆和表,编号):基本车辆(表,编号){} 虚拟浮点getMaxSpeed()常量{return 40.0f;}//常量 虚拟浮点getWeight()常

将属性从派生类传递到基类的机制是什么,以便:

  • 基本用户可以访问它们
  • 它们可以很容易地存储在STL容器中
  • 外部的任何人都只能在派生类上访问它们
  • 有效性不是很有价值

属性是一个与派生类的每个对象相关的常量。

可以虚拟执行,也可以非虚拟执行。但要回答其中哪一个是最好的,让我们检查一下您的示例:

class自行车:公共车辆
{
公众:
自行车(可行驶车辆和表,编号):基本车辆(表,编号){}
虚拟浮点getMaxSpeed()常量{return 40.0f;}//常量
虚拟浮点getWeight()常量{return 10.0f;}//常量
虚浮点getLength()常量{return 2.3f;}//常量
虚拟int getWheels()常量{return 2;}//常量
};
这些函数中的每一个都返回一个常量,但仍然需要一个虚拟调用来获取该常量。这是一种糟糕的做法,因为您需要执行(昂贵的)虚拟调用来获取每个值

更好的方法:使用
struct
相反,最好将这些常量传递给父类的构造函数,并将这些常量存储在基类中。这样,您根本不需要访问
BaseVehicle
vtable
,只需直接在基类内部访问即可。像这样:

struct vehiclests{
浮动最大速度;
浮重;
浮子长度;
int车轮;
};
//BaseVehicle的构造函数现在变成:
基本车辆(车辆表、编号、车辆测试统计)
或者,您只能在
基本车辆
中创建一个
虚拟
功能:

virtualvehiclests getStats()const=0;
这肯定比创建四个单独的函数要好

替代方法:使用
enum
您还可以将表示车辆类型的
enum
传递给父级。例如:

enum类车辆类型{
自行车,
汽车
};
//BaseVehicle的构造函数现在变成:
基本车辆(车辆表、编号、车辆类型统计)
然后全局存储统计信息:

static const std::map globalStatsMap;

如果您有大量的统计数据,并且不想增加基类的内存大小,那么这是一个非常好的方法。现在,您根本不需要
BaseVehicle
的实例,仍然可以根据类型查找属性。

从所示内容来看,您根本不需要继承:

struct VehicleAttributes
{
    float maxSpeed;
    float weight;
    float length;
    int   wheelsCount;
};

class Vehicle
{
private:
    Vehicle(VehicleTable& table, Number number, const VehicleAttributes& attributes): m_image(attributes.length, attributes.wheelsCount), m_attributes(&attributes)
    {
        table.registerVehicle(*this, number);
    }

public:
    static Vehicle BiCycle(VehicleTable& table, Number number)
    {
        static const VehicleAttributes bicycleAttributes{40, 10, 2.3, 2};

        return Vehicle(table, number, bicycleAttributes);
    }
    static Vehicle Car(VehicleTable& table, Number number)
    {
        static const VehicleAttributes carAttributes{88, 42, 2.5, 4};

        return Vehicle(table, number, carAttributes);
    }

    const VehicleAttributes& getAttributes() const { return *m_attributes; }

private:
    Image m_image;
    const VehicleAttributes* m_attributes = nullptr;
    float m_speed = 0; // the current speed
};
如果您的问题是“将属性从派生类传递到基类的机制是什么?”那么有两种方法可以做到这一点

  • 最常见的方法是通过成员初始值设定项列表初始化父类
  • #包括
    阶级基础
    {
    公众:
    基本(常量字符*a)
    {
    
    代码中没有“与派生类的每个对象相关的常量”,因此代码和文本之间的联系不清楚。您发布的代码有什么问题/缺失?@idclev463035818虚拟函数表示常量。因此,问题是如何在基类构造函数中访问它们?或者使用什么来代替虚拟函数?@idclev463035818 Yes我无法再次跟随您的参数st要点3.如果你需要一个值来构造一个对象,那么将其作为参数传递给构造函数是自然的,而不是“阻碍的”。如果你不想让构造函数公开,你可以将其设置为受保护的。此外,这并不“假设允许它创建具有任何属性的基本对象”(至少与任何构造函数的情况不同),基类和派生类都仍然可以检查有效参数并相应地执行操作。此代码非常糟糕。您仍然在调用
    getLength()
    getWheels()
    在初始值设定项列表中,您拼错了
    VehicleAttributes
    ,您拼错了
    VehicleAttributes
    ,您没有用地址初始化
    m_属性
    ,并且默认情况下为其分配
    nullptr
    ,即使它总是初始化的。@J.Schultke:我没有意识到以前的构造函数调用这是虚拟方法。我希望我修复了拼写错误(更容易用IDE/compiler捕获;-)。我忘记了
    &
    获取地址(也有拼写错误:/)。我更喜欢默认为
    nullptr
    初始化每个指针/内置,即使总是初始化(在出错时更容易调试)。