2016-12-07 57 views
0

我是C++的新手(更多的是java人)。我正在尝试自我介绍C++指针。在这里我创建了两个类,Person(基类)和Student(派生类)。C++传递指向模板类的函数

我试图把Student对象放在unordered_map<string, Person>中。但遇到了一个错误。

这是我的代码:

class Person 
{ 
    protected: 
    string name; 
    int age; 

    public: 
    int getAge() 
    { 
     return age; 
    } 
    string getName() 
    { 
     return name; 
    } 
}; 

class Student : public Person 
{ 
    private: 
    string grade; 

    public: 
    Student(string const &name, int const &age, string const &grade) 
    { 
     this -> name = name; 
     this -> age = age; 
     this -> grade = grade; 
    } 
    int getAge(); 
}; 

这是我的主要功能:

int main() 
{ 
    unordered_map<string, Person *> students; 
    Student s("Sam", 26, "A"); 
    Person *p; 
    p = &s; 

    students.insert(p -> getName(), p); 

    return 0; 
} 

这仅仅是一个代码的一部分,我知道它看起来愚蠢的。但我只是了解指针

我已包括<iostream><unordered_map>库和使用namespace std在这里。

错误消息太长了。有人能指出我在这里所犯的错误吗?或者,我是否应该发布那个长的错误信息呢? 在此先感谢。

+1

你可以使用students.insert({p - > getName(),p}); – user1438832

+0

*“错误消息太长了。”*答案是*“太大而不能放在边距中”* :-) – Jarod42

+0

但是,我的代码有什么问题? –

回答

2

我多一个java的家伙。

这里有您需要知道:

指针

Person*是指向一个人 - 一个指针只需携带一个对象在内存中的地址。这是你可以得到的低水平。这相当于在汇编语言中使用地址寄存器或索引寄存器。它不包含关于对象生命周期的信息,也不会以任何方式影响对象生命周期。这是100%滥用。如果有的话,小心使用。

共享引用

// java code 
var x = new Y(); 
var y = x; 

// equivalent c++ 
auto x = std::make_shared<Y>(); 
auto y = x; 

如果你想类似Java的行为,那么std::shared_ptr<Person>相当于一个Java对象引用。它共享该人的所有权,并允许(实际上在C++中)当所有shared_ptrs已经超出范围或已被重置时该人被销毁。

与寿命控制

两者之间唯一的参考是一个std::unique_ptr<Person>,这将导致该人的自动销毁当所述一个和唯一的unique_ptr被破坏或复位。您不能复制std::unique_ptr,因此它不能用于共享对象的引用。但是,它可以转换为shared_ptr(这隐含地清空unique_ptr)。

弱引用

然后有一个std::weak_ptr<Person>这是弱对应的std::shared_ptr<Person>。它不能直接取消引用,但必须先用lock()方法将其转换为shared_ptr。这提供了一个原子'测试存在和锁定到位'的操作。我们使用它来解决或避免由循环引用引起的资源泄漏(java声称不会因垃圾回收而导致资源泄漏)。当没有一个对象更可达引用的Java和C++

在Java中,之间

寿命的差异,它变成用于垃圾收集一个候选。在未来的某个时候,它可能会或不会被恢复。

C++是不同的和更可预测的。当控制对象的生命期的unique_ptr或最后一个shared_ptr重置时,该对象的析构函数将立即在同一个线程中执行。这是完全顺序的。这产生了RAII的可能性,并且允许我们使用对象生命周期来使代码执行,而不管执行路径如何。

这也可以说是为什么在C++中不需要finally。资源清理进入资源所有者的破坏者。

+0

哇。感谢您提供更详细解释的答案。这是一个很大的帮助! –

1

您的代码看起来不错,但有一个行:

students.insert(p -> getName(), p); 

在这里,您可能意味着要放置p到小区p->getName(),但不幸的是,std::unordered_map::insert没有实例取一个键和一个价值作为两个参数。将它们作为一个变量或使用operator[]应该有所帮助:

students[p->getName()] = p; 
students.insert({p->getName(), p}); 
students.insert(std::make_pair(p->getName(), p)); 

我个人会选择第一个选项是更具可读性如果可能的话。

UP: As @ Jarod42评论说,这里的第一个选项要求值类型是默认可构造的,这并不总是一个选项。

+1

第一个选项要求该值是默认可构造的,但情况并非总是如此。 'emplace'是另一种可能性。 – Jarod42

+0

@ Jarod42谢谢,这是一个重要的说明。将添加到答案。 – alexeykuzmin0

+0

谢谢@ alexeykuzmin0 –

1
int main() 
{ 
    unordered_map<string, Person *> students; 
    Student s("Sam", 26, "A"); 
    Person *p; 
    p = &s; 

    pair<string, Person*> item("key", p); 
    students.insert(item); 

    return 0; 
}