【问题标题】:How to make inherited base classes use a common variable如何使继承的基类使用公共变量
【发布时间】:2016-02-24 06:34:59
【问题描述】:

假设我想创建一个界面

  1. Items 有可以阅读的内容。
  2. Items 有可写的内容。
  3. Items 的内容可以读写

但是我不想创建 3 个抽象类,因为我可能想传递一个 Item,它对只接受可读项目的函数是可读写的。

例如你只能读取Book,所以Book会继承Readable,而Note可以读写,所以它会继承ReadWritable

所以现在我可以创建这样的函数了:

std::string read(Readable& readable) const

void take_a_note(Writable& writable)

我有这个Readable 抽象类

template <typename ReadableType>
class Readable
{
public:
    Readable(const ReadableType content);
    virtual ~Readable(void);
    virtual auto content(void) const noexcept -> const ReadableType&&;

private:
    const ReadableType _content;
};

还有一个Writable 抽象类

template <typename WritableType>
class Writable
{
public:
    Writable(void);
    virtual ~Writable(void);
    virtual void content(WritableType&& content) noexcept;

private:
    WritableType _content;
};

但现在我想创建一个结合了这些功能的抽象类,称为ReadWritable

template <typename ReadWritableType>
class ReadWritable: public Readable<ReadWritableType>, public Writable<ReadWritableType>
{
public:
    ReadWritable(ReadWritableType content);
    virtual ~ReadWritable(void);
    using Writable<ReadWritableType>::content;
    using Readable<ReadWritableType>::content;
};

这就是问题所在,因为content(WritableType&amp;&amp; content) 使用Writable::_content,而content(void) 使用Readable::_content

如何让它们使用相同的 _content 数据成员。如果我能做到这一点,有没有办法删除另一个?


或者我的完整方法是错误的?我愿意接受所有意见。

【问题讨论】:

  • 我不确定你的问题是否正确 - 但是你看过虚拟基类的概念吗?这将确保派生的 ReadWritable 类中只有一个 _content 成员
  • 我认为这仅适用于基类是完全相同的基础,例如如果我继承了 Readable 两次。问题不是真的有过载,而是 Readable::content() 和 Writable::content() 都有自己的私有变量_content,它们不会协调
  • 分离接口和实现。接口不应该存储任何状态,你应该在实现中存储所有状态。
  • 我不认为模板是这种情况下更好的用法,你不想为每个特定的可重写和可写对象创建代码,但你的类希望得到一个填充接口的对象,如前所述@tofro,您应该检查虚拟课程。

标签: c++ inheritance multiple-inheritance base-class


【解决方案1】:

我不确定我的问题是否正确,但据我了解,您希望让两个单独的类共享相同的数据,并且仍然使用这些共享数据继续它们的功能。

我已经测试了几种组合,以下代码运行良好。但是我不得不做出一些改变:

#include <iostream>

class ReadableType
{
    public: int id=0;
            int* sharedValue;
};

class WritableType
{
    public: int id=1;
            int* sharedValue;
};

class ReadWritableType
{
    public: int id=2;
            int* sharedValue;
            ReadWritableType(int share){sharedValue = new int;*sharedValue = share;};
};

class Readable
{
public:
    void content(void){std::cout << "id: "<<_content->id <<" sharedValue: "<<*_content->sharedValue<<std::endl;};

protected:
    ReadableType *_content;
};


class Writable
{
public:
    void content(WritableType content){std::cout << "id: "<<_content->id <<" sharedValue: "<<*_content->sharedValue<<std::endl;};

protected:
    WritableType *_content;
};


class ReadWritable: public Readable, public Writable
{
public:
    ReadWritable(ReadWritableType* content);
    using Writable::content;
    using Readable::content;
private:
    void makeReadable(ReadWritableType* content);
    void makeWritable(ReadWritableType* content);
};

ReadWritable::ReadWritable(ReadWritableType* content)
{
    makeReadable(content);
    makeWritable(content);
}

void ReadWritable::makeReadable(ReadWritableType* content)
{
    Readable::_content = new ReadableType();
    Readable::_content->sharedValue = content->sharedValue;
}

void ReadWritable::makeWritable(ReadWritableType* content)
{
    Writable::_content = new WritableType();
    Writable::_content->sharedValue = content->sharedValue;
}
int main()
{
    ReadWritable x(new ReadWritableType(5));
    WritableType s;
    x.content();
    x.content(s);   
}

输出是每个 _content 使用一个私有值 (id) 和一个共享值 (sharedValue),它们在两个 _contents 之间共享相同的内存。

【讨论】:

    【解决方案2】:

    加上一层,你可以这样做

    template <typename ReadableType>
    class IReadable
    {
    public:
        virtual ~IReadable() = default;
        virtual const ReadableType& content() const noexcept = 0;
    };
    
    template <typename WritableType>
    class IWritable
    {
    public:
        virtual ~IWritable();
        virtual void content(WritableType&& content) noexcept = 0;
    };
    
    template <typename ReadableType>
    class Readable : public IReadable
    {
    public:
        Readable(const ReadableType& content);
        virtual const ReadableType& content() const noexcept override;
    private:
        const ReadableType _content;
    };
    
    template <typename WritableType>
    class Writable
    {
    public:
        virtual void content(WritableType&& content) noexcept override;
    private:
        WritableType _content;
    };
    

    最后:

    template <typename ReadWritableType>
    class ReadWritable: public IReadable<ReadWritableType>, public IWritable<ReadWritableType>
    {
    public:
        ReadWritable(ReadWritableType content);
    
        virtual void content(WritableType&& content) noexcept override;
        virtual const ReadableType& content() const noexcept override;
    private:
        ReadWritableType _content;
    };
    

    您确实必须重新实现ReadWritable::content,但代码可以用Readable/Writable 分解并重用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多