- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我在写一个侵入式链表
class ListAlgorithm {
ListNode& next(ListNode& n) {
//returns an object of type ListNode linked to n.
}
};
用户通常希望像这样在ListNode上添加一些特性(比如一些额外的数据):
class UserNode : public ListNode {
void operationOnUserData();
int userData;
};
然后用户必须将'next'返回的ListNode向下转换为UserNode。这很不方便。因此,我试图让 ListAlgorithm 成为一个模板类:
//U extends ListNode
template<class U>
class ListAlgorihtm {
U& next(U& u);
};
但随后我必须在“next”方法中将 u 向上转换为 ListNode,因为类 U 可能会意外地隐藏 ListAlgorithm 使用的 ListNode 的某些成员。这很容易出错,因为我可能会忘记向上转换,而编译器不会对此发出警告。我必须再次将 ListNode 向下转换为 U 以获得返回值,但这是安全的,因为“next”采用 U 的实例 u 并且返回值是来自 u 的内容。
另一个试验是
//U extends ListNode
template<class U>
class ListAlgorhtm {
U& next(ListNode& n);
};
在这种情况下,向上转型的问题不存在,但我必须将ListNode向下转型为U作为返回值并且它不安全,因为它不确定n是U的实例。它可能是的实例另一种扩展 ListNode 的类型。
在这种情况下最好的解决方案是什么?我认为这是一个非常初级的设计问题,我想知道对于这样的基本 OO 设计我需要学习什么样的 Material 。
最佳答案
这里的实际问题是您允许用户子类化 ListNode
并通过向 ListNode
对象添加任意数据和操作来混淆其语义通过子类化。因此,从语义上讲,这使得用户有必要将实际 ListNode
方法的 ListNode&
返回值解释为那些返回值不是的东西.
这个语义问题反射(reflect)在你的代码突然变得多么乏味,一个不相关的类(ListAlgorithm
)的转换和模板化是由于你的问题“传播”和感染其他部分你的代码。
这是一个解决方案:ListNode
对象不应同时是 UserNode
对象。但是,应该允许它拥有、携带一个可以检索和操作的 UserData
对象。
换句话说,您的列表变成了一个简单的容器模板,如 std::list
,用户可以指定他们需要的操作和数据成员作为他们定义的类的一部分用作模板参数。
class IListNode
{
public:
// whatever public methods you want here
protected:
// pure virtual methods maybe?
};
class ListNode : public IListNode
{
// List node class, no data
};
template<class UserDataType>
class ListNodeWithData : public IListNode
{
private:
UserDataType data;
public:
ListNodeWithData <UserDataType>(UserDataType &data) :
data(data)
{ }
const UserDataType& getData() {
return data;
}
};
class ListAlgorithm
{
public:
template<class UserDataType>
ListNodeWithData<UserDataType>& next(const ListNodeWithData<UserDataType>& node) {
// Do stuff
}
ListNode& next(const ListNode& node) {
// Do stuff, which may be very similar to the stuff done above
// in which case you may want to prefer to just define the
// method below, and remove this one and the one above:
}
// You should define either this method or the two above, but having
// them all is possible too, if you find a use for it
IListNode& next(const IListNode& node) {
// Do generic stuff
}
};
就生成的类的大小而言,我只知道如果在 IListNode 中使用虚方法,它会增加。
关于c++ - 面向侵入式数据结构的面向对象设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26957199/
我是一名优秀的程序员,十分优秀!