c++ 这是一种不明确的行为吗?

cu6pst1q  于 2023-01-28  发布在  其他
关注(0)|答案(2)|浏览(140)

我试图用一些额外的功能扩展std::mapstd::pair条目,并想将这样的对强制转换为对子类的子类。注意,这是多态的"错误"方向,子类 * 不是 * 父类。但由于只要我不在子类中引入额外的成员,内存布局就应该是相同的,我想知道这是否有效。
下面是一个最小的例子:

#include <iostream>
#include <map>
#include <string>

class Concatenator : public std::pair<const std::string, std::string> {
public:
  operator std::string() const { return first + ", " + second; }
};

int main() {
  std::map<std::string, std::string> m{{"hello", "world"}};

  // Is this defined behavoiur?
  Concatenator &c{*static_cast<Concatenator *>(&*m.begin())};
  std::cout << std::string{c} << std::endl;
}
2ledvvac

2ledvvac1#

但是由于只要我不在子类中引入额外的成员,内存布局就应该是相同的......
不,那是不对的。那是不明确的行为。
即使没有多重继承,也不能保证内存布局是相同的。即使内存布局 * 是 * 相同的,那么 * 它仍然是未定义的行为。不要这样做 *。

rpppsulh

rpppsulh2#

我认为这是很好的定义:

#include <iostream>
#include <map>
#include <string>

class Concatenator : public std::pair<const std::string, std::string> {
public:
    using base = std::pair<const std::string, std::string>;
    Concatenator(const base& o) : base(o) {}
    operator std::string() const { return first + ", " + second; }
};

int main() {
  std::map<std::string, std::string> m{{"hello", "world"}};

  Concatenator c = *m.begin();
  std::cout << std::string{c} << std::endl;
}

相关问题