如何使用模块化架构避免重复功能

How to avoid duplicating functions with a modular architecture

我正在尝试使用 C++ 实现模块化架构,其中每个 .cpp 文件都有一个 .h 文件。这些文件目前只有空函数:

cycle.h

#include <iostream>
#ifndef CYCLIST_H
#define CYCLIST_H
#pragma once

class cyclist{
private:
    double width;
    double length;
    int helment;
public:
    void Predict();
    double get_width();
    double get_length();
    int get_helmet();
};

#endif

cycle.cpp

#include <iostream>
#include "cyclist.h"

void cyclist::Predict(){std::cout << "Predict something!" << std::endl;}
double cyclist::get_width(){}
double cyclist::get_length(){}
int cyclist::get_helmet(){}

vehicle.h

#include <iostream>
#ifndef VEHICLE_H
#define VEHICLE_H
#pragma once

class vehicle{
private:
    double width;
    double length;
    int number_of_doors;
public:
    void Predict();
    double get_width();
    double get_length();
    int get_number();
};

#endif

vehicle.cpp

#include <iostream>
#include "vehicle.h"

void vehicle::Predict(){std::cout << "Predict something!" << std::endl;}
double vehicle::get_width(){}
double vehicle::get_length(){}
int vehicle::get_number(){}

如您所见,我重复了 get_wdith()get_height()Predict() 函数。原因是他们每个人都会有相同功能的不同实现。

如何从基数 class 中导出所有这些函数?如果我使用基础 class、would/can 我仍然使用 .h 个文件?

编辑

所以我创建的是一个单独的头文件Base.h,如下所示:

#include <iostream>
#pragma once

class Base{
    public:
        virtual ~Base() = default;
        virtual void Predict() = 0;
        virtual double get_width() = 0;
        virtual double get_length() = 0;
        virtual int get_number_of_doors() = 0;
        virtual bool get_helmet_state();
};

然后我决定像这样从自行车手和车辆 class 继承这些:

cyclist.cpp

#include <iostream>
#include "Base.h"

void Base::Predict(){std::cout << "Predict something!" << std::endl;}
double Base::get_width(){return 0;}
double Base::get_length(){return 0;}
bool Base::get_helmet_state(){return true;}

vehicle.cpp

#include <iostream>
#include "Base.h"

void Base::Predict(){std::cout << "Predict something!" << std::endl;};
double Base::get_width(){return 0;}
double Base::get_length(){return 0;}
int Base::get_number_of_doors(){return 0;}

现在,当我 运行 它时,我收到一条错误消息,指出 Base::Predict() 有多个定义。此功能将在每个 class 中以不同的方式实现。我尝试添加 override 关键字,但它不允许。

第一步:应用 Liskov Substitution Principle 以确保继承有意义。

步骤One-A:确保Composition isn't a better fit

第二步:制作基地 class

class Base // For demonstration purposes only. Give this a more descriptive name in your code
{ 
public: 
    virtual ~Base() = default;
    virtual void Predict() = 0;
    virtual double get_width() = 0;
    virtual double get_length() = 0;
};

如果你愿意,可以在自己的 header 中弹出它。没有什么可以阻止继承层次结构的使用和划分为 headers.

取决于你的用例,you may or may not need the destructor,但如果你正在学习 C++,让你的生活更轻松并把它放进去。拥有它可能会在运行时浪费一些时间,但你会遇到更少的怪事如果您的经验不足导致您误入歧途,则必须调试的问题。

您要覆盖的所有函数都必须声明 virtual. virtual is sticky, so you don't have to keep repeating it in the derived classes, but keep an eye out for final

virtual 末尾的 = 0 函数 makes them pure 并使 class 抽象。这可能是也可能不是您想要的行为,但它们中的每一个都有不同的实现 强烈暗示它是。阅读链接文档以确保确定。

第三步:继承

class cyclist: public Base{
private:
    double width;
    double length;
    int helment;
public:
    void Predict() override;
    double get_width() override;
    double get_length() override;
    int get_helmet();
};

请注意,override keyword 不是硬性要求,但它可以通过剔除错误为您省去很多麻烦,只需几秒钟即可键入,编译时间微不足道,并且在运行时绝对没有。世界上有几种 win-win 情况,所以要好好利用这一点。

附录:

如果您在覆盖函数中的 class 之间共享行为,请考虑将共享行为的代码移动到 protected 支持函数中,并从覆盖函数中调用支持函数以消除重复。

class Base // For demonstration purposes only. Give this a more descriptive name in your code
{ 
protected: 
    double predict_support();
public: 
    virtual ~Base() = default;
    virtual void Predict() = 0;
    virtual double get_width() = 0;
    virtual double get_length() = 0;
};

以后 Base.cpp

double Base::predict_support()
{
    return do_complicated_math();
}

然后像

一样使用它
void cyclist::Predict()
{
    std::cout << "Predict something: " << predict_support() << std::endl;
}