我正在寻找这个特定问题的解决方案。
我有一个IOWriter
模板类,有几种写入不同类型值的方法。
现在在我的基类TestBase
中,我创建了一个带有通用ref输入的函数模板。这会将值转发给基类的IOWriter
类实例。
在派生类TestDerived
中,我有一个专门的IOWriter (i.e. Writer)
类成员实例writer
,它应该由自己的函数模板调用以进行转发。
template <typename WriterType>
struct IOWriter
{
template < typename T >
QString Write(WriterType* obj, T value)
{
std::cout << "Not Working: TestBase" << std::endl;
return obj->write(QString("true"));
}
};
class TestBase
{
template <typename T>
friend struct IOWriter;
//Uses default implementation
IOWriter<TestBase> writer;
// pure virtual function called by IOWriter
virtual QString write(const QString& value) = 0;
public:
template <typename T>
QString Write(T&& value)
{
return writer.Write(this, std::forward<T>(value));
}
};
class TestDerived : public TestBase
{
template <typename T>
friend struct IOWriter;
// TestDerived specific implementation
struct Writer : public IOWriter<TestDerived>
{
// Shadows base implementation
QString Write(TestDerived* obj, bool value)
{
std::cout << "Working: TestDerived" << std::endl;
return obj->write(QString("false"));
}
};
Writer writer;
// Called by Writer
QString write(const QString& value) override
{
return "derived";
}
public:
template <typename T>
QString Write(T&& value)
{
return writer.Write(this, std::forward<T>(value));
}
};
现在在我的代码中我可以这样称呼它:
void working()
{
int value = 0;
auto uptr = new TestDerived();
uptr->Write(value);
delete uptr;
}
工作正常。但是,当我将创建的指针存储为TestBase时,它逻辑上调用TestBase::Write
,因此永远不会调用TestDerived::writer
:
void notWorking()
{
int value = 0;
TestBase* uptr = new TestDerived();
uptr->Write(value);
delete uptr;
}
现在我知道这是正确的,但我正在寻找一种方法让TestBase::Write
使用/调用专门的TestDerived::Writer
而不是自己的。{/ p>
注意: IOWriter不能拥有虚函数,因为那里有模板成员函数
答案 0 :(得分:1)
哦,程序员生活中的美好时光,当他/她意识到设计不符合需求并考虑重写大部分代码时......我喜欢它:D
好的,首先必须与问题无关,但仍然是:
好的,不是手头的问题:
我看到的一个解决方案是使Bridge Pattern适应您的问题:
这意味着:
Write
虚拟<{li>的IOWriter
TestBase
中writer
指向IOWriter
的多态基指针TestDerived::writer
而非Writer
IOWriter
Write
TestDerived
方法
这是最终的代码:(我用int更改了QSString以便能够更快地测试它):
的final code
强>
template <typename WriterType> struct IOWriter
{
virtual int Write(WriterType* obj, int value)
{
return obj->write(value * 10 + 3);
}
virtual ~IOWriter() = default;
};
struct TestBase
{
//Uses default implementation
std::unique_ptr<IOWriter<TestBase>> writer;
TestBase(std::unique_ptr<IOWriter<TestBase>> writer) : writer{std::move(writer)} {}
// pure virtual function called by IOWriter
virtual int write(int value) = 0;
template <typename T> int Write(T value)
{
return writer->Write(this, value);
}
virtual ~TestBase() = default;
};
struct TestDerived : public TestBase
{
// TestDerived specific implementation
struct Writer : public IOWriter<TestBase>
{
// Shadows base implementation
int Write(TestBase* obj, int value) override
{
return obj->write(value * 10 + 4);
}
};
TestDerived() : TestBase(std::make_unique<Writer>()) {}
// Called by Writer
int write(int value) override
{
return value;
}
};
auto test()
{
std::unique_ptr<TestBase> uptr = std::make_unique<TestDerived>();
return uptr->Write(7);
}