我该怎么做才能删除或最小化将提供相同功能和行为的代码重复?

我有一组派生类,并且正在使用一个函数在实例化或创建类时自动更新其内部ID值。最初,我在他们的基类或超类中具有此功能,并且正在工作,可以给我正确的结果。但是,作为设计决定,我正在更改此行为。

在第一个版本中,每次构造Component对象时,即使子类型不同,附加的数值也会增加。我不要这种行为。我希望每个子类都从[0]开始并计数...

我移动了执行该计算的函数,将新值附加到从基础类到派生类的成员string id上。但是,这现在正在创建代码重复项,并且使用当前的设计,每个将来的子类都必须实现此功能...

我希望拥有与当前相同的功能和行为,但是无需重复代码!


这是我当前的输出,这是我在显示ID时要寻找的行为:

Successfully connected Wire_001 to Wire_005
         from Wire_001 to Bus_000
Successfully connected Wire_002 to Wire_006
         from Wire_002 to Bus_000
Successfully connected Wire_003 to Wire_007
         from Wire_003 to Bus_000
Successfully connected Wire_000 to Wire_005
         from Wire_000 to Bus_000
Component Wire_000 already exists in Wire_004!
         from Wire_000 to Bus_000

Successfully connected Wire_001 to Wire_000
Successfully connected Wire_002 to Wire_001
Successfully connected Wire_003 to Wire_002
Successfully connected Wire_000 to Wire_003

Successfully connected Wire_004 to Wire_008
         from Wire_004 to Bus_001
Successfully connected Wire_005 to Wire_009
         from Wire_005 to Bus_001
Successfully connected Wire_006 to Wire_010
         from Wire_006 to Bus_001
Successfully connected Wire_007 to Wire_011
         from Wire_007 to Bus_001

These are my connected components:
        Wire_004 has Wire_000

        Wire_005 has Wire_001 Wire_000

        Wire_006 has Wire_002

        Wire_007 has Wire_003

这是我当前的源代码:

main.cpp

#include <exception>

#include "Bus.h"

int main() {
    try {
        Wire w1,w2,w3,w4;
        std::cout << w1.id() << " " << w2.id() << " " << w3.id() << " "<< w4.id() << "\n\n";

        Bus<4> b1;

        b1.connect(&w1,0);
        b1.connect(&w2,1);
        b1.connect(&w3,2);
        b1.connect(&w4,3);

        b1.connect(&w1,1);  // Valid Connection: same wire to multiple bus wires
        b1.connect(&w1,0);  // Invalid Connection: trying to connect a same wire to the same bus wire multiple times...
        std::cout << "\n";

        Bus<4> b2;
        w1.connect(&w2);
        w2.connect(&w3);
        w3.connect(&w4);
        w4.connect(&w1);
        std::cout << "\n";

        b2.connect(&b1.wire(0),0);
        b2.connect(&b1.wire(1),1);
        b2.connect(&b1.wire(2),2);
        b2.connect(&b1.wire(3),3);

        std::cout << "\nThese are my connected components:\n";
        for( size_t i = 0; i < b2.size(); i++ ) {
            for (auto& component : b2.myConnections(i)) {
                std::cout << "\t" << component->id() << " has ";
                auto connections = component->myConnections();
                for (auto& c : connections) {
                    std::cout << c->id() << " ";
                }
                std::cout << '\n';
            }
            std::cout << '\n';
        }
                     
    } catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

Component.h

#pragma once

#include <assert.h>   
#include <memory>    
#include <array>
#include <list>    
#include <iomanip>
#include <iostream>    
#include <string>
#include <sstream>    

class Component {
protected:
    std::string id_ = "";
    std::list<std::shared_ptr<Component>> components_;

    explicit Component(const std::string& id) : id_{ id } {}

public:
    virtual ~Component() {}

    std::string& id() { return id_; }

    void connect(Component* other) {
        for (auto& l : components_) {
            if (other->id_ == l->id()) {
                std::cout << "Component " << other->id_ << " already exists in " << id_ << "!\n";
                return;
            }
        }

        components_.push_back( std::make_shared<Component>( *other ) );
        std::cout << "Successfully connected " << other->id() << " to " << id_ << "\n";
    }

    virtual std::list<std::shared_ptr<Component>> myConnections() { return components_; }    
    virtual void propagate() {};    
};

Wire.h

#pragma once

#include "Component.h"

class Wire : public Component {
private:

public:
    explicit Wire(const std::string& name = "Wire") : Component(name) {
        updateId();
    };
       
    virtual ~Wire() {}

    virtual void propagate() override {
        return;
    }

private:
    void updateId() {
        static int i = 0;
        std::stringstream strValue;
        strValue << std::setw(3) << std::setfill('0') << std::to_string(i++);
        id_.append("_" + strValue.str());
    }
};

Bus.h

#pragma once

#include "Wire.h"

template<size_t BusSize>
class Bus : public Component {
private:
    std::array<std::shared_ptr<Wire>,BusSize> bus_interface_;

public:
    explicit Bus(const std::string& name = "Bus") : Component(name) {
        updateId();
        createBus();
    }

    virtual ~Bus() {}

    virtual void propagate() override {
        return;
    }

    void connect(Component* component,size_t index) {
        assert(index < BusSize);
        assert(component != nullptr);
        bus_interface_[index]->connect(component);
        std::cout << "\t from " << component->id() << " to " << id_ << "\n";
    }

    Wire& wire(size_t index) {
        assert(index < BusSize);
        return *bus_interface_[index].get();
    }

    std::array<std::shared_ptr<Wire>,BusSize> bus() { return bus_interface_; }

    std::list<std::shared_ptr<Component>> myConnections(size_t index) { 
        assert(index < BusSize);
        return bus_interface_[index]->myConnections();
    }

    size_t size() const { return BusSize; }

private:
    void updateId() {
        static int i = 0;
        std::stringstream strValue;
        strValue << std::setw(3) << std::setfill('0') << std::to_string(i++);
        id_.append("_" + strValue.str());
    }

    void createBus() {
        size_t i = 0;
        for (auto& w : bus_interface_) {
            w = std::shared_ptr<Wire>(new Wire);
        }
    }
};

从这两个子类中可以看到,它们的成员函数::updateId()

void updateId() {
    static int i = 0;
    std::stringstream strValue;
    strValue << std::setw(3) << std::setfill('0') << std::to_string(i++);
    id_.append("_" + strValue.str());
}

是我关注的代码重复。在保持相同功能和行为的同时,我该怎么做以消除此代码重复的依赖性?

iCMS 回答:我该怎么做才能删除或最小化将提供相同功能和行为的代码重复?

您可以使用CRTP。添加一个模板化的第二基类来保存ID处理代码。

template <class T>
class ComponentID {
public:
    ComponentID(std::string &id_) {
        // Same as updateID above
    }
};

class Wire: public Component,ComponentID<Wire> {
public:
    Wire(const std::string& name = "Wire") : Component(name),ComponentID(id_) {
    }
    // ...
};

template<size_t BusSize>
class Bus : public Component,ComponentID<Bus<BusSize>> {
    public:
        explicit Bus(const std::string& name = "Bus") : Component(name),ComponentID(id_) {
            createBus();
        }
        // ...
};

我们将id_基类的Component字段传递给ComponentID构造函数,以便可以更新它而不必更改对id的访问权限

本文链接:https://www.f2er.com/1979365.html

大家都在问