指针和类之间的交互

时间:2014-11-21 14:31:54

标签: c++ class pointers object c++11

我最近一直在努力学习来自java和其他高级语言背景的c ++。我一直遇到指针和对象的一些问题,我还没有找到一个很好的资源来解释如何使用指针操作使用自定义类创建的对象。

我写了一个简单的程序,试图缩小我的问题范围。

这个类底部的最后两个代码块是错误的,我敢打赌,我在其他部分也做了一些错误。任何帮助表示赞赏。

#include <iostream>
#include <cstdlib>
#include <string.h>

using namespace std;

class Point {
public: 
    float x;
    float y;    
public: 
    Point(float x, float y) {
        this->x=x;
        this->y=y;
    }
    Point() {
        x=0.0f;
        y=0.0f;
    }
    ~Point() {
        x=0.0f;
        y=0.0f;
    }
};

class Place {
public: 
    string name;
    Point location;
public: 
    //Constructor with arguements.
    Place(string nam, Point loc) {
        name = nam;
        location = loc;
    }
    //Default constructor.
    Place() {
        name = "Default";
        location = {0.0f,0.0f};
    }
    //Destructor. This object contains no pointers so nothing to delete.
    ~Place() {

    }
public: 
    void setName(string nam) {
        name = nam;
    }
    void setLocation(Point loc) {
        location = loc;
    }
};

class PointerToAPlace {
public: 
    Place *place;
public:
    PointerToAPlace(Place *pl) {
        *place = *pl;
    }
    ~PointerToAPlace() {
        delete place;
    }
};

int main(int argc, char** argv) {
    std::cout << "\n";
    std::cout << "Make some places and hope they don't segfault.\n";


    /*Object created with default constructor. Will be automatically deleted at the end of this scope.*/
    Place placeA;
    std::cout << "Place named " << placeA.name.c_str() << " is at " << placeA.location.x << "," << placeA.location.y << " and is lovely.\n";
    //Output: Place named Default is at 0,0 and is lovely.


    /*Object created with bracket constructor. Will be automatically deleted at the end of this scope.*/
    Place placeB = {"Lordran", Point{12.2f,99.3f}};
    std::cout << "Place named " << placeB.name.c_str() << " is at " << placeB.location.x << "," << placeB.location.y << " and is lovely.\n";
    //Output: Place named Lordran is at 12.2,99.3 and is lovely.


    /*Object created with new keyword. This is a pointer and must be explicitly deleted.*/
    Place *placeC = new Place("Drangleic", Point{-123.34f,69.69f});
    std::cout << "Place named " << placeC->name.c_str() << " is at " << placeC->location.x << "," << placeC->location.y << " and is lovely.\n";
    delete placeC;
    //Output: Place named Drangleic is at -123.34,69.69 and is lovely.


    /*Array of objects, created with default constructor and not assigned any values. Will be automatically deleted at the end of this scope.*/
    Place placeD[3];
    std::cout << "Here are some places named: ";
    for(int i=0;i<3;i++) {
        std::cout << placeD[i].name.c_str();
        std::cout << (i<2 ? ", " : ". ");
    }
    std::cout << "They are quite the places!\n";
    //Output: Here are some places named: Default, Default, Default. They are quite the places!    


    /*Array of objects, created with default constructor and then assigned values. Will be automatically deleted at the end of this scope.*/
    Place placeE[5];
    string namesA[5] = {"Boletaria", "Stonefang", "Latria", "Shrine of Storms", "Valley of Defilement"};
    for(int i=0;i<5;i++) {
        placeE[i].setName(namesA[i]);
        placeE[i].setLocation(Point{1.23f, 3.21f});
    }
    std::cout << "Here are some places named: ";
    for(int i=0;i<5;i++) {
        std::cout << placeE[i].name.c_str();
        std::cout << (i<4 ? ", " : ". ");
    }
    std::cout << "They are quite the places!\n";
    //Output: Here are some places named: Boletaria, Stonefang, Latria, Shrine of Storms, Valley of Defilement. They are quite the places!


    /*Trying to do a pointer to an array of objects.*/
    Place *placeF[7];
    string namesB[7] = {"Astora", "Carim", "Thoroughland", "Catarina", "Baulder", "Vinheim", "Zena"};
    for(int i=0;i<7;i++) {
        placeF[i]->setName(namesB[i]);
        placeF[i]->setLocation(Point{2.23f, 6.21f});
    }
    std::cout << "Here are some places named: ";
    for(int i=0;i<7;i++) {
        std::cout << placeF[i]->name.c_str();
        std::cout << (i<6 ? ", " : ". ");
    }
    std::cout << "They are quite the places!\n";
    //Output: SEGFAULT D:

    /*Trying to put a pointer to a place into an object, then delete it.*/
    Place *placeG = new Place("Anor Londo", Point{-12312.34f,33.69f});
    PointerToAPlace pnt = {placeG};
    std::cout << "Place named " << pnt.place->name.c_str() << " is at " << pnt.place->location.x << "," << pnt.place->location.y << " and is lovely.\n";
    //Output: SEGFAULT :(

    return 0;
}

4 个答案:

答案 0 :(得分:6)

PointerToAPlace(Place *pl) {
    *place = *pl;
}

这是错误的,如果您尝试做的是存储指针然后执行此操作:

PointerToAPlace(Place* pl) {
    place = pl;
}

或者更好的是,使用构造函数初始化列表:

PointerToAPlace(Place* pl) : place(p1) {
}

您当前的代码没有设置place,因此它包含一个指向谁知道在哪里的垃圾值,然后取消引用它(这是未定义的行为)。

你还需要注意复制PointerToAPlace,目前如果你复制它,你会得到两个持有相同指针的对象,并且两者都会尝试删除它。

恕我直言,一旦您了解了语法如何工作以及如何使用new / delete,您应该停止使用它们并使用智能指针。

答案 1 :(得分:3)

class PointerToAPlace {
public: 
    Place *place;
public:
    PointerToAPlace(Place *pl) {
        *place = *pl;
    }
    ~PointerToAPlace() {
        delete place;
    }
};

一开始就错了。在将其指向任何地方之前,您需要引用place

据推测,你的意思是place = pl; *是类型的一部分,而不是名称。

如果您将指针声明编写为Place* pl,而不是Place *pl,则会更清楚。不要听从20世纪70年代那些对多变量声明的边缘情况着迷的反对者,因为这些只是唯一这种符号的缺点。

答案 2 :(得分:2)

/*Trying to do a pointer to an array of objects.*/
Place *placeF[7];

不,这是指向Place的七个(未初始化的)指针的数组。因此,当您取消引用它们时,您会遇到段错误。

答案 3 :(得分:0)

您应该在类中添加一个复制构造函数。 如果没有,当将类实例推入堆栈时,您将遇到麻烦。 复制构造函数是一个构造函数,它将相同的类实例作为参数:

Point(Point & original)
{
  // initialize this with original
}

编辑:添加缺失'&amp;'在代码段中。

相关问题