说我有 private void functionMap() {
"<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><meta http-equiv=\"Content-Type\" content=\"text/html,width=device-width,user-scalable=yes; charset=windows-1252\">\n" +
" <script type=\"text/javascript\" src=\"https://www.google.com/jsapi\"></script>\n" +
" <script type=\"text/javascript\">\n" +
" google.load('visualization', '1', {'packages': ['geochart']});\n" +
" google.setOnLoadCallback(drawRegionsMap);\n" +
"\n" +
" function drawRegionsMap() {\n" +
" var data = google.visualization.arrayToDataTable([\n" +
" ['Country', ''],\n"
" ]);\n" +
"\n" +
" var options = {};\n" +
"\t\toptions = { \n" +
" datalessRegionColor: '#29ABE2',\n" +
"\t\t\t\t backgroundColor: '#F3F3F3',\n" +
"\t\t\t\t\tcolorAxis: {colors: ['#0071BC']},\n" +
" keepAspectRatio: false, \n" +
" legend: false,\n" +
" tooltip: { textStyle: { color: '#0099CB', fontName: 'Arial', fontSize: '10'} }\n" +
" };\n" +
"\t\t\n" +
" var chart = new google.visualization.GeoChart(document.getElementById('chart_div'));\n" +
" chart.draw(data, options);\n" +
" };\n" +
" </script>\n" +
" </head>\n" +
" <body>\n" +
" <div id=\"chart_div\" style=\"width: 100%; height: 100%;\"><div style=\"position: relative;\"><div dir=\"ltr\" style=\"position: relative; width: 100%; height: 100%;\"><div style=\"position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;\"></div></div></div></div>\n" +
" \n" +
"</body></html>";
}
的纯课程A
和课程B
,C
,D
等。是否有可能从A
的析构函数中知道哪个派生类正在被销毁?
答案 0 :(得分:4)
这取决于你需要什么。当然,人们会在这里质疑为什么,这是一个值得怀疑的愿望。
在编译时不可能随时自动从基类中知道对象的动态类型。如果您想知道编译时的类型,唯一的解决方案是将该信息包含在基类类型本身中,这基本上就是CRTP模式。例如:
class BaseBase {
// body
};
template <typename D>
class Base : BaseBase {
//body
};
class Derived1 : public Base<Derived1> {
// body
};
class Derived2 : public Base<Derived2> {
// body
};
这样Base
的析构函数将在编译时#34;知道&#34;编译时派生类的类型。然而,这有一个缺点,即Derived1
和Derived2
的常见超类型不 Base
,但BaseBase
和BaseBase
析构函数不知道(你可能会回到原点)。
如果您只想在运行时知道(这意味着您不能直接执行DerivedClass::something
之类的操作),例如出于调试原因,您可以在包含类型信息的基类中添加成员:
class Base {
protected:
type_info const* type;
public:
Base() {
type = &typeid(this);
}
};
class Derived : public Base {
public:
Derived() {
type = &typeid(this);
}
};
请注意,这取决于Base
构造函数将在Derived
构造函数之前运行的事实,因此type
指针将引用当前已构造的最派生类。
答案 1 :(得分:3)
可以在使用CRTP时完成,如下所示:
template <typename TDerived>
class Base {};
class Derived : public Base<Derived> {};
然后Base
始终知道派生类型。
答案 2 :(得分:0)
CRTP的问题在于你有不同的基类型,你不能将它们用于动态多态。
如果您不需要派生对象的实际类型,但想要根据它执行代码,则有不同的可能性。请注意,您无法在析构函数中调用任何虚函数。但是,您可以:
1。添加一个类型成员变量(无论是std::type_info
,枚举还是其他)并在其上手动调度。
2。使用技术作为virtual constructor idiom的对应物,在显式销毁之前调用函数(通过delete
或类似)。但是,这可能会被遗忘,或者(如果强制执行)严重限制了如何销毁对象。
3。您可以使用策略模式:
class Base
{
struct Strategy
{
virtual ~Strategy();
virtual void onDestroy() = 0;
}
std::unique_ptr<Strategy> strategy;
public:
explicit Base(std::unique_ptr<Strategy> strategy)
: strategy(std::move(strategy))
{
}
virtual ~Base()
{
strategy->onDestroy();
}
};
class Derived1 : public Base
{
struct Strategy1 : Strategy
{
virtual void onDestroy() { ... }
};
public:
Derived1()
: Base(std::make_unique<Strategy1>())
{
}
};
请注意,使用C ++ 11函数对象,这变得非常简单:
class Base
{
std::function<void()> strategy;
public:
explicit Base(std::function<void()> strategy)
: strategy(std::move(strategy))
{
}
virtual ~Base()
{
strategy();
}
};
class Derived1 : public Base
{
public:
Derived1()
: Base([] () { ... })
{
}
};
重要:您必须确保策略对象或函数对象不引用派生类的任何成员,因为派生对象在调用时已被销毁。如果您需要访问成员属性,最好直接重新定义析构函数。