我有一个简单的IO类,带有线程安全的getter和setter。 它看起来像这样:
template <class IO>
class LIO : public LThreadSafe
{
public:
LIO() {}
IO getValue()
{
this->lock();
IO ret = value;
this->unlock();
return ret;
}
void setValue( IO newval )
{
this->lock();
value = newval;
this->unlock();
}
LInput<IO> *toInput()
{
return (LInput<IO> *)this;
}
private:
IO value;
某些类需要能够读取和写入这些IO。 而其他人应该只被允许阅读。 所以我创建了一个Input类,我可以将我的IO类转换为
template <class IO>
class LInput : public LThreadSafe
{
public:
LInput() {}
IO getValue()
{
this->lock();
IO ret = value;
this->unlock();
return ret;
}
private:
IO value;
这是好习惯吗? 为此创建一个全新的类似乎过分了。
解决方案
我最终得到了多重继承。一旦我对shared_ptr和C ++更加熟悉,就会检查这个帖子。 希望我能更多次按向上箭头......
答案 0 :(得分:2)
我能想到的,有两种方法。
您可以将LInput
私有继承自LIO
,但将输入方法标记为公开:
template <typename IO>
class LIO : public LThreadSafe
{
public:
LIO() {}
LIO(const LIO& in) { /* make a copy for read-only */ }
LIO(LIO& io) { /* make a copy for write-only */ }
shared_ptr<LInput<IO>> toInput() const { return make_shared<LInput<IO>>(*this); }
shared_ptr<LOutput<IO>> toOutput() { return make_shared<LOutput<IO>>(*this); }
};
template <class IO>
class LInput : private LIO
{
public:
LInput(LIO<IO>* pio) : LIO<IO>(*pio) {}
using LIO<IO>::getValue;
};
LInput<int> in;
auto v = in.getValue(); // OK
in.setValue(xyz); // Error: inaccessible
LIO<int>& io = in; // Error: inaccessible
再次考虑这个解决方案,你会发现可以复制IO对象是件好事。如果无法复制,则需要在LIO
类中包装实现类引用。
如果你无法复制,一个完整的例子就是:
template <typename IO> class LIOImpl {};
template <typename IO> class LInput;
template <typename IO> class LOutput;
template <typename IO> class LIO {
shared_ptr<LIOImpl<IO> > pimpl_;
public:
LIO() : pimpl_(make_shared<LIOImpl<IO> >()) {}
LIO(const LIO &io) : pimpl_(io.pimpl_) {}
IO getValue() const { ... }
LInput<IO> toInput() const { return LInput<IO>(*this); }
LOutput<IO> toOutput() { return LOutput<IO>(*this); }
};
template <class IO> class LInput : private LIO<IO> {
public:
LInput(const LIO<IO> &io) : LIO<IO>(io) {}
using LIO<IO>::getValue;
};
template <class IO> class LOutput : private LIO<IO> {
public:
LOutput(LIO<IO> io) : LIO<IO>(io) {}
using LIO<IO>::setValue;
};
C ++ STL iostream
使用多重继承方式来实现istream
和ostream
。在hirarchy中提出了约束。这个钻石继承有时被认为是一种不好的做法。
这种下推约束方法避免了钻石继承。
您还可以使用
template <typename IO>
class LInput
{
public:
virtual IO getValue() const = 0;
};
template <typename IO>
class LOutput
{
public:
virtual void setValue(const IO& v) const = 0;
};
template <typename IO>
class LIO : public LInput<IO>, public LOutput<IO>, public LThreadSafe
{
public:
IO getValue() const override { ... }
void setValue(const IO& v) const override { ... }
LInput<IO>* toInput() const { return this; }
LOutput<IO>* toOutput() { return this; }
};
选择您感觉良好的方式,同时尝试将您的界面与实现隔离开来。一旦达到限制,(或者您只是不喜欢它),您可以轻松更改界面而无需重新实现。
顺便说一句,如果您使用的是C ++ 11,则应使用std::lock_guard而不是手写lock/unlock
对:
{
lock_guard<LThreadSafe> lock;
// ok you have lock now.
}
// here lock is automatically released