- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个具有以下继承层次结构的库(模型):
struct Xbase {
virtual void f() = 0;
};
struct Derived1 : public Xbase {
void f() { std::cerr << "Derived1::f\n"; }
};
struct Derived2 : public Xbase {
void f() { std::cerr << "Derived2::f\n"; }
};
struct Storage {
std::map<int, Xbase*> data;
Xbase* get(int i) {
auto it = data.find(i);
return (it == data.end() ) ? nullptr : it->second;
}
};
该库跟踪指向基本结构的指针,并允许检索它们,在这个小例子中是通过一个整数 id。有一个使用该库的应用程序,并希望通过引入第二个基类 Ybase 来提供一些功能:
struct Ybase {
virtual void g() { std::cerr << "Ybase::g\n"; }
};
struct AppDerived1 : public Derived1, public Ybase {
void f() { std::cerr << "AppDerived1::f\n"; }
};
struct AppDerived2 : public Derived2, public Ybase {
void f() { std::cerr << "AppDerived2::f\n"; }
};
当然是这样
int i = 5;
Storage storage;
Xbase* xbase = storage.get(i);
Ybase* ybase = static_cast<Ybase *>(xbase);
工作不是很好
$ g++ -std=c++11 t.cpp
t.cpp: In function ‘int main()’:
t.cpp:21:45: error: invalid static_cast from type ‘Xbase*’ to type ‘Ybase*’
我想提供派生类的模板版本,以便应用程序开发人员可以将他的类插入到库层次结构中。
图书馆:
template<typename T>
struct Derived1 : public T {
void f() { std::cerr << "Derived1::f\n"; }
};
应用所有者:
struct Ybase : public Xbase {
virtual void g() { std::cerr << "Ybase::g\n"; }
};
struct AppDerived1 : public Derived1<Ybase> {
...
};
/* same for AppDerived2 */
Xbase* xbase = storage.get(i);
Ybase* ybase = static_cast<Ybase *>(xbase);
ybase->g();
这会创建一个单一的继承线,并且转换应该有效。
我想知道这是好主意还是坏主意,还有什么可以替代。请注意,我确实需要层次结构中的公共(public)基类 Xbase,因为我必须能够从名称和 ID 等外部数据中检索基类指针。应用程序开发人员的问题是应用程序还需要其基指针,因为应用程序不知道它接收到的对象的类型(AppDerived1 或 2)。感谢阅读。
最佳答案
您不能将 Xbase*
转换为 Ybase*
,因为它们是不相关的类。
但是,由于多重继承和动态转换,如果您知道可以使用的最多派生类,则可以安全地从 Xbase 转换为 Ybase:
Ybase* ybase{};
Derived1 *pd1 = dynamic_cast<Derived1*>(xbase); // is it a Derived 1 ?
if (pd1) { // if yes
AppDerived1 *app = dynamic_cast<AppDerived1*>(pd1); // Then look for an AppDerived 1
if (app) // If valid cast
ybase = app; // we can cass the AppDerived1 to an Ybase
}
else { // same approach for the second type
Derived2 *pd2 = dynamic_cast<Derived2*>(xbase); // is it a Derived 2 ?
if (pd2) { // if yes
AppDerived2 *app = dynamic_cast<AppDerived2*>(pd2);
if (app)
ybase = app;
}
} // if ybase is still nullptr here, it means that we couldn't find a valid conversion path
cout << (ybase ? "Success " : "Fail ") << (void*)ybase << endl;
这可以利用您的对象结构和合法的上下转换:
您的替代方案建立在将自己限制在单一继承层次结构的原则之上。您类(class)的设计完全不同。你假设一个 Ybase 是一个 Xbase(总是):
这是否好完全取决于您尝试表示的应用程序域。如果在现实中 Ybase 始终是 Xbase,这将非常有意义。
这里我只能引用 Bjarne Stroustrup:
Independent concepts should be independently represented and should becombined only when needed. Where this principle is violated, youeither bundle unrelated concepts together, or create unnecessarydependencies. Either way you get less flexible set of components.
关于C++ 库 : application inserts a class in inheritance hierarchy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29113952/
我是一名优秀的程序员,十分优秀!