我有Base和Derived类 基地:
class Person{
public:
Person(string name , int age ){
this -> name = name;
this -> age = age;
}
virtual void getInfo(){
cout << "Person " << name << " " << age;
}
protected:
string name;
int age;
};
派生:
class Kid : public Person{
public:
Kid(string name, int age):Person(name,age){};
virtual void getInfo( ){
cout << "Kid " << name << " " << age;
}
};
class Adult : public Person{
public:
Adult(string name, int age):Person(name,age){};
virtual void getInfo( ){
cout << "Adult " << name << " " << age;
}
};
当我做
之类的事情map<string ,Person*> m;
Person *one;
Person *three;
Kid two("Mathew",15);
Adult four("JOhn",55);
three = &four;
one = &two;
m["first"] = one;
m["second"] = three;
for( auto &x : m )
x.second-> getInfo();
return 0;
它很好地打印信息,因为它应该//&#34;成人&#34;成人班和&#34;孩子&#34;为孩子班
然而,当我编辑类并将地图移动到基类时。例如,创建Add
方法。
class Person{
public:
Person(string name , int age ){
this -> name = name;
this -> age = age;
}
virtual void getInfo(){
cout << "Person " << name << " " << age;
}
void add( string name , Person a){
Person *one = &a;
m[ name ] = one;
}
void print(){
for( auto &x: m )
x.second -> getInfo()
}
protected:
string name;
int age;
map< string , Person*> m;
};
Person one("John", 25);
one.add("first",Kid("Mathew",15));
one.add("second",Adult("Leo",55));
one.print();
它抛出了seg故障,为什么会发生这种情况?它与使用方法基本相同。是什么导致了seg故障?有办法解决它吗?
//编辑
我尝试使用unique_ptr重新映射地图
map< string , unique_ptr<Person>> m;
AddField (string name , Person a ){
m[name] = ( unique_ptr<Person> (a));
return *this;
}
或
properties[name] = unique_ptr<Person> ( new Person( a ));
或
AddField (string name , Person a ){
CData *one = unique_ptr<Person>(new Person(a));
m[name] = one ;
return *this;
}
我对unique / share ptr没有经验。 这扔了
'std :: unique_ptr'到'人*'
答案 0 :(得分:2)
首先,让我们了解地图实际存储的内容:
map< string , Person*> m;
此映射将字符串绑定到Person*
,这是指向某个人的内存地址。地图实际上并不存储人员实例,只存储其内存地址。
现在让我们分析你的两种情况。
map<string ,Person*> m;
// Allocating space for two memory addresses on the stack:
Person *one;
Person *three;
// Creating two instances on the stack:
Kid two("Mathew",15);
Adult four("JOhn",55);
// Setting the pointers to the memory addresses of the instances on the stack:
three = &four;
one = &two;
m["first"] = one;
m["second"] = three;
for( auto &x : m )
x.second-> getInfo();
return 0;
// End of the function: now all objects are destroyed in reverse order.
实例two
和four
存在于堆栈中,并在范围的末尾(return 0;
之后)被销毁。获取内存地址并将其存储到one
和three
中是很好的,因为指针将比two
和four
更长。
Person one("John", 25);
// Creating a Kid instance without a name (temporary).
// The Kid instance goes out of scope immediately and is destroyed:
one.add("first",Kid("Mathew",15));
// Creating an Adult instance without a name (temporary).
// The Adult instance goes out of scope immediately and is destroyed:
one.add("second",Adult("Leo",55));
one.print();
这里的问题是您正在创建的实例过早销毁。您需要正确管理它们的生命周期,以确保您插入到映射中的内存地址不会超过指向内存位置中的数据。
另一个主要问题是您按值接受add
的{{1}}参数。这将创建传递的实例的副本。
Person a
您应该将// Copy the passed instance:
void add( string name , Person a){
// Take memory address of the copied instance:
Person *one = &a;
m[ name ] = one;
// The copied instance is destroyed here!
}
作为参考,以避免副本和object slicing:
a
在更正void add( string name , Person& a){
m[ name ] = &a;
}
的签名后,这是一个有效的示例:
a
答案 1 :(得分:1)
我试图解决你的问题,我想出了一个初始版本。我并不满意。
#include<iostream>
#include<map>
#include<memory>
#include<string>
/* used to simplify example code (not a good
idea in production code especially header files)
*/
using namespace std;
class Person
{
public:
virtual void getInfo() const = 0;
virtual ~Person()
{};
void add(std::shared_ptr<Person> a)
{
m_[a->name_] = a;
}
void print() const
{
getInfo();
for( auto &x: m_ )
x.second->getInfo();
}
protected:
Person(const string& name, int age)
: name_(name), age_(age)
{}
string name_;
int age_;
map<string , std::shared_ptr<Person>> m_;
};
class Kid : public Person
{
public:
Kid(const string& name, int age)
: Person(name, age)
{};
virtual void getInfo() const override
{
cout << "Kid " << name_ << " " << age_ << '\n';
}
};
class Adult : public Person
{
public:
Adult(const string& name, int age)
: Person(name, age)
{};
virtual void getInfo() const override
{
cout << "Adult " << name_ << " " << age_ << '\n';
}
};
int main()
{
auto a = Adult("steve", 35);
auto k1 = make_shared<Kid>("ben", 7);
auto k2 = make_shared<Kid>("emily", 12);
a.add(k1);
a.add(k2);
a.print();
}
我使用shared_ptr
,因为我猜测您可能希望从地图中检索这些Person
并从 getter 调用中返回它们。所以在这种情况下unique_ptr
毫无意义。
我认为这个版本给调用者带来了太多的负担来创建shared_ptr
。虽然很难提出替代方案,但却不知道你打算做什么。