请看这个链接:https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(C4503)&rd=true建议写:
// C4503b.cpp
// compile with: /W1 /EHsc /c
#include <string>
#include <map>
class Field{};
struct Screen2 {
std::map<std::string, Field> Element;
};
struct WebApp2 {
std::map<std::string, Screen2> Element;
};
struct WebAppTest2 {
std::map<std::string, WebApp2> Element;
};
struct Hello2 {
std::map<std::string, WebAppTest2> Element;
};
Hello2 MyWAT2;
而不是
// C4503.cpp
// compile with: /W1 /EHsc /c
// C4503 expected
#include <string>
#include <map>
class Field{};
typedef std::map<std::string, Field> Screen;
typedef std::map<std::string, Screen> WebApp;
typedef std::map<std::string, WebApp> WebAppTest;
typedef std::map<std::string, WebAppTest> Hello;
Hello MyWAT;
但是这些代码与typedef Hello
是std::map
不等同,而struct
s只是一个结构,其字段为map
这意味着我不能互换使用它们。有人可以解释这个伎俩吗?
答案 0 :(得分:4)
你是对的,你不能互换使用它们。实际上,Microsoft建议您这样做是为了克服技术上的困难:他们无法(或有困难)处理超过4096字节的错位名称。
在大多数情况下,我相信typedef
对聚合来说是更好的解决方案。
但是由于你的编译器有些限制,你可能会陷入困境。
答案 1 :(得分:3)
如果你想要一个能够实现区分(受损,可能被截断)名称的目标的解决方案,但没有额外的命名层的缺点,你可以使用继承:
class Screen : public std::map<std::string, Field>
{
// forward constructors here
};
答案 2 :(得分:0)
提供的变通方法不是作为重现器的等效替代品,而是作为可能的方式来减少导出符号的修饰长度。
您可以使用简单objdump /symbols objfile.obj
验证使用typedef
s的装饰符号的长度比分成struct
的类似对应长度要长得多(Microsoft编译器历来使用过专有名称修改方案)。
答案 3 :(得分:0)
typedef
没有声明新类型,它只是一个别名。如果你转发声明typedef
,当编译器看到typedef
定义时,它会引发错误:
// a.hpp
class Screen;
class any_class_using_screen {};
// a.cpp
#include "a.hpp"
typedef std::map<std::string, Field> Screen; // Error.
使用简单的继承允许您将自定义名称用于其他类型:
class Screen : public std::map<std::string, Field>
{};
请记住,没有其他成员的简单继承不会导致任何内存或时间开销。这与typedef
一样有效,并且它是一种新类型。
由于std::map<...>
没有虚拟析构函数,因此不能使用&#34;指针指向基类&#34;当然,像往常一样。 Screen
实例的所有者(创建screen
实例的实例),如果它存在于堆中并且必须被破坏,则必须从指向派生类的指针中删除:
template<class K, class V>
void f(std::map<K, V> const* map); // Do something
int main()
{
Screen* s = new Screen;
f(s); // Ok
delete s; // OK, deleting from derivate class
}
@ PeterA.Scheneider建议,就派生类没有其他成员而言,没有任何反应,你可以从指向派生类的指针调用析构函数。但是,theoretically
,没有虚拟析构函数,你正在破坏基类实例(只有基类生命到达它的结尾),并且派生类实例仍然存在,具有死基,具有损坏的对象。从实际的角度来看,我认为对象被正确破坏了,但无论如何我都不知道这是否会导致不确定的行为。
应该检查标准以确定。
此外,从基类指针破坏没有额外成员的派生对象的方法可能存在对齐问题。
如果基类没有虚拟析构函数,那么在没有&#34;多态意图&#34;的情况下继承,并且总是从派生类最多的类中进行析构。