将属性传递给基类的机制

如何解决将属性传递给基类的机制

将属性从派生类传递到基类的机制是什么?

  • 基本ctor可以访问它们。
  • 它们可以轻松地存储在STL容器中。
  • 外面的任何人都可以访问它们,只能在派生类上“看到”。
  • 有效性并不是很有价值。

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

解决方法

如果您的问题是“将属性从派生类传递到基类的机制是什么?”有两种方法可以做到这一点。

  1. 最常见的方法是通过成员初始值设定项列表
  2. 初始化父类
#include <iostream>

class Base
{
public:
    Base(const char *a)
    {
        std::cout << a << std::endl;
    }
};

class Derived : public Base
{
public:
    Derived(const char *a)
    : Base{a} { }
};

int main()
{
    Derived d{"Parent initialization through member initializer list"};
    // console output: Parent initialization through member initializer list
}
  1. 使用键通过获取构造函数继承
#include <iostream>

class Base
{
public:
    Base(const char *a)
    {
        std::cout << a << std::endl;
    }
};

class Derived : public Base
{
public:
    using Base::Base;
};

int main()
{
    Derived d{"Parent class initialization through constructor inheritance"};
    // console output: Parent class initialization through constructor inheritance
}

看看带有模板类的有用示例

#include <iostream>
#include <vector>

template<class T>
class custom_vector : public std::vector<T>
{
public:
    // I will inherit all std::vector constructors
    using std::vector<T>::vector;
    // ...
};

int main()
{
    // Inizializer list constructor
    custom_vector<int> v{1,2,3,4,5};
    for (auto x : v) std::cout << x << std::endl;
    // 1 2 3 4 5
 
    // Fixed-allocation with default value constructor
    custom_vector<char> v2(10,'A');
    for (auto x : v2) std::cout << x << std::endl;
    // A A A A A A A A A A
}

不用使用std :: vector :: vector ,我就不会继承std :: vector构造函数。

在您的示例中,我注意到一些设计缺陷

  • 虚拟函数不用于将属性传递给基类
  • 我不明白你为什么提到模板
  • 您不应重复使用virtual关键字,因为它在派生类中已经是虚拟的,可以使用override关键字。
  • 通常不建议使用部分实现的抽象类,您应该考虑从BaseVehicle中删除m_image和m_speed。在某些情况下,在抽象类中进行一些实现实际上是有用的,但只有在您有充分理由的情况下才这样做。
  • 在抽象类的构造函数中具有类似* table.registerVehicle( this,number)的语句是一种不良的设计症状。
,

您可以虚拟或非虚拟方式进行操作。但是,要回答其中哪一个最好,让我们检查一下您的示例:

class Bicycle: public BaseVehicle
{
public:
    Bicycle(VehicleTable& table,Number number): BaseVehicle(table,number) {}

    virtual float getMaxSpeed() const { return 40.0f; } // constant
    virtual float getWeight()   const { return 10.0f; } // constant
    virtual float getLength()   const { return 2.3f;  } // constant
    virtual int   getWheels()   const { return 2;     } // constant
};

这些函数中的每个函数都返回一个常量,但仍需要进行虚拟调用才能获取该常量。这是不理想的做法,因为您需要执行(昂贵的)虚拟调用才能获取每个值。

更好的方法:使用struct

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

struct VehicleStats {
    float maxSpeed;
    float weight;
    float length;
    int wheels;
};

// BaseVehicle's constructor now becomes this:
BaseVehicle(VehicleTable& table,Number number,VehicleStats stats)

或者,您只能在virtual中创建一个BaseVehicle函数:

virtual VehicleStats getStats() const = 0;

这肯定比创建四个单独的函数更好。

替代方法:使用enum

您还可以将代表车辆类型的enum传递给父级。例如:

enum class VehicleType {
    BICYCLE,CAR
};

// BaseVehicle's constructor now becomes this:
BaseVehicle(VehicleTable& table,VehicleType stats)

然后您将统计信息全局存储:

static const std::map<VehicleType,VehicleStats> globalStatsMap;

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

,

根据显示的内容,您根本不需要继承:

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

class Vehicle
{
private:
    Vehicle(VehicleTable& table,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,carAttributes);
    }

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

private:
    Image m_image;
    const VehicleAttributes* m_attributes = nullptr;
    float m_speed = 0; // the current speed
};

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-