鉴于
#include <string>
#include <iostream>
struct A {
virtual operator std::string() const { return "A"; }
virtual operator const char *() const { return this->operator std::string().c_str(); }
};
struct B1 : public A {
virtual operator std::string() const { return "<"; }
};
struct B2 {
B2() { }
virtual ~B2() { }
virtual operator std::string() const { return ">"; }
virtual operator const char *() const { return this->operator std::string().c_str(); }
};
struct C1 : public A {
C1() { }
virtual ~C1() { }
virtual operator std::string() const { return "["; }
};
struct C2 {
C2() { }
virtual ~C2() { }
virtual operator std::string() const { return "]"; }
virtual operator const char *() const { return this->operator std::string().c_str(); }
};
int main() {
using namespace std;
cout << B1() << endl;
cout << C1();
cout << C2() << B2() << endl;
}
输出应为“&lt; []&gt;”。但是,它是“&lt; []]”。
答案 0 :(得分:5)
实际上,由于以下原因,您的代码行为未定义:
return this->operator std::string().c_str();
您正在临时调用c_str()
,并稍后使用该结果。
您所看到的是未定义行为的有效表现。
现在,如果您对实际发生的事情感到好奇,可以将main()
的最后一行修改为:
cout << (const void*)C2() << ' ' << (const void*)B2() << endl;
如果你这样做,你可能会看到相同的地址被打印两次(在两种情况下都是悬空指针)。这就是我的电脑上发生的事情,我怀疑你的电脑会发生什么。 当然,由于行为未定义,这只是许多人的一种可能表现。
答案 1 :(得分:3)
你的问题真的归结为:
#include <string>
#include <iostream>
struct B2 {
B2() { }
virtual ~B2() { }
virtual operator std::string() const { return ">"; }
virtual operator const char *() const { return this->operator std::string().c_str(); }
};
struct C2 {
C2() { }
virtual ~C2() { }
virtual operator std::string() const { return "]"; }
virtual operator const char *() const { return this->operator std::string().c_str(); }
};
int main() {
using namespace std;
cout << C2() << B2() << endl;
}
很明显,这与虚拟功能无关。这里发生的是调用operator const char*
,调用operator std::string
,返回一个临时std::string
,您可以从中返回.c_str()
。由于在调用operator const char*
之后此临时std::string
被销毁,因此您有const char*
指向已释放的内存。
现在任何事都可能发生,因为这是UB ......