对象指针的矢量,一般帮助和混淆
Vector of Object Pointers, general help and confusion
有一个家庭作业,我应该在其中创建一个指向对象的指针向量
稍后,我将使用继承/多态性来扩展类,以包括两天的交付、第二天的广播等费用。然而,这不是我现在关心的问题。当前程序的最终目标是打印出矢量中每个对象的内容(名称和地址),并找到它的运输成本(重量*成本)。
我的问题不在于逻辑,我只是对与对象/指针/向量相关的几点感到困惑。但首先是我的代码。我基本上删掉了现在不重要的东西,int main,将有用户输入,但现在我硬编码了两个例子。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Package {
public:
Package(); //default constructor
Package(string d_name, string d_add, string d_zip, string d_city, string d_state, double c, double w);
double calculateCost(double, double);
~Package();
private:
string dest_name;
string dest_address;
string dest_zip;
string dest_city;
string dest_state;
double weight;
double cost;
};
Package::Package()
{
cout<<"Constucting Package Object with default values: "<<endl;
string dest_name="";
string dest_address="";
string dest_zip="";
string dest_city="";
string dest_state="";
double weight=0;
double cost=0;
}
Package::Package(string d_name, string d_add, string d_zip, string d_city, string d_state, string r_name, string r_add, string r_zip, string r_city, string r_state, double w, double c){
cout<<"Constucting Package Object with user defined values: "<<endl;
string dest_name=d_name;
string dest_address=d_add;
string dest_zip=d_zip;
string dest_city=d_city;
string dest_state=d_state;
double weight=w;
double cost=c;
}
Package::~Package()
{
cout<<"Deconstructing Package Object!"<<endl;
delete Package;
}
double Package::calculateCost(double x, double y){
return x+y;
}
int main(){
double cost=0;
vector<Package*> shipment;
cout<<"Enter Shipping Cost: "<<endl;
cin>>cost;
shipment.push_back(new Package("tom r","123 thunder road", "90210", "Red Bank", "NJ", cost, 10.5));
shipment.push_back(new Package ("Harry Potter","10 Madison Avenue", "55555", "New York", "NY", cost, 32.3));
return 0;
}
所以我的问题是:
- 有人告诉我必须使用矢量对象指针,而不是对象。为什么?我的任务需要它具体来说,但我也被告知否则不会起作用
- 我应该在哪里创建矢量?它应该是我包裹的一部分吗班如何添加然后把物体放进去
我需要复制构造函数吗?为什么?
解构的正确方式是什么我的对象指针矢量?
如有任何帮助,我们将不胜感激。我在这里搜索了很多相关的文章,我意识到我的程序会有内存泄漏。使用boost::中的一个专用ptr将不可供我使用。现在,我更关心的是为我的项目打下基础。通过这种方式,我实际上可以深入到我需要创建的功能。
谢谢。
指针向量可以重复用于存储子类的对象:
class Person
{
public:
virtual const std::string& to_string () = 0;
virtual ~Person () { }
};
class Student : public Person
{
const std::string& to_string ()
{
// return name + grade
}
};
class Employee : public Person
{
const std::string& to_string ()
{
// return name + salary
}
};
std::vector<Person*> persons;
person.push_back (new Student (name, grade));
person.push_back (new Employee (name, salary));
person[0]->to_string (); // name + grade
person[1]->to_string (); // name + salary
理想情况下,向量应该封装在一个类中。这使得内存管理更加容易。它还便于在不破坏现有客户端代码的情况下更改支持数据结构(此处为std::vector
):
class PersonList
{
public:
Person* AddStudent (const std::string& name, int grade)
{
Person* p = new Student (name, grade);
persons.push_back (p);
return p;
}
Person* AddEmployee (const std::string& name, double salary)
{
Person* p = new Employee (name, salary);
persons.push_back (p);
return p;
}
~PersonList ()
{
size_t sz = persons.size ();
for (size_t i = 0; i < sz; ++i)
delete persons[i];
}
private
std::vector<Person*> persons;
};
因此,我们可以将代码重写为:
{
PersonList persons;
Person* student = persons.AddStudent (name, grade);
Person* employee = persons.AddEmployee (name, salary);
student.to_string ();
employee.to_string ();
} // The memory allocated for the Person objects will be deleted when
// `persons` go out of scope here.
熟悉"三条规则"将有助于您决定何时将复制构造函数添加到类中。另请阅读有关常量正确性的内容。
问题1:你提到了继承。由于继承的对象通常需要更多字节的存储空间,因此它们不适合放置基本对象。如果你试图把它们放进去,你会得到一个基础对象。这称为对象切片。
问题2:先设计,然后再编写代码。有很多可能的解决方案。首先,您可以将它保存在main()中,但稍后您将被迫创建一个类似PackageContainer
的类来保存对象。
问题3+4:当类对象拥有动态分配的对象时,您需要一个复制构造函数、一个赋值运算符=和一个析构函数(三巨头规则)。因此PackageContainer
可能需要它们。可以使用new Object(..)
动态创建对象。你要负责销毁它们,并在你的指针向量被销毁之前立即将它们的内存还给系统:
for (size_t i = 0; i < shipment.size(); ++i)
{
delete shipment[i];
}
由于使用指向动态分配对象的裸指针是不安全的,请考虑使用
std::vector<tr1::shared_ptr<Package> > shipment;
而不是
std::vector<std::shared_ptr<Package> > shipment;
如果您的编译器理解C++0x。shared_ptr
为您释放内存:它为一个对象指针实现了三大规则。应在生产质量代码中使用。
但也要试着用裸指针把它做好。我想这就是你的家庭作业。
有人告诉我必须使用对象指针的向量,而不是对象。为什么?我的任务特别要求它,但我也被告知否则它不会起作用
通常,人们会避免使用对象向量来避免对象切片的问题。要使多态性发挥作用,必须使用某种指针。我不确定你的赋值中的类是如何对齐的,但你可能在某个地方有继承,因此,如果向量存储基类的对象,并且你在其中插入派生类的对象,那么它会导致派生类成员切片。
最好的解决方案是使用智能指针而不是Raw指针。STL有一个auto_ptr
,但不能在标准容器中使用。Boost智能指针将是最好的解决方案,但正如您已经说过的,您不能使用Boost。因此,在您的情况下,您可以使用编译器的智能指针实现,它位于TR1
命名空间中,但请记住,在TR1函数的命名空间上存在一些分歧(Visual C++将它们放在std::
中,而GCC将它们放进std::tr1::
中)。
我应该在哪里创建这个向量?它应该是我的一揽子课程的一部分吗?那么我该如何向其中添加对象呢
您的示例代码已经有一个在向量中添加指向Package
类的指针的示例。简而言之,您将动态地为Package
分配指针,然后将它们添加到向量中。
我需要复制构造函数吗?为什么
编译器生成的复制构造函数执行成员复制。有时这还不够。例如:
class MyClass {
public:
MyClass( const char* str );
~MyClass();
private:
char* str;
};
MyClass::MyClass( const char* str2 )
{
str = new char[srtlen( str2 ) + 1 ];
strcpy( str, str2 );
}
Class::~Class()
{
delete[] str;
}
在这种情况下,按成员方式复制str
成员不会复制缓冲区(只复制指针(shallow copy
)),因此共享缓冲区的第一个要销毁的副本将成功调用delete[]
,第二个将运行到Undefined Behavior
。在这种情况下,您需要deep copying copy constructor
(以及赋值运算符)。
何时使用自定义复制构造函数最好由三规则:定义
Whenever you are writing either one of Destructor, Copy Constructor or Copy Assignment Operator, you probably need to write the other two.
解构对象指针向量的正确方法是什么
您必须在每个包含的指针上显式调用delete来删除它所指向的内容。
vector::erase
从向量容器中移除并调用其析构函数,但如果包含的对象是指针,则它不会拥有销毁它的所有权。
请在此处查看此答案,了解如何正确删除指向对象的指针向量。
- 在指针的帮助下,文本文件中单词的频率
- C++指针/数组(我现在完全困惑,真的需要帮助)
- 指针帮助:取消指向访问其内部数据的结构的指针
- 函数和指针帮助:程序生成,但崩溃,没有任何特定错误
- C 指针节点帮助 - 将参数复制到链接的列表节点更改该节点的不同部分
- 作业帮助,分割故障,双免费或腐败,免费():无效的指针
- C++中的指针帮助
- 需要帮助了解指针变量分配
- BST c++ 中的指针帮助
- C 帮助(ISO C 禁止指针和整数之间的比较.)
- C++ 指针帮助缺少参数列表使用 &帐户::获取余额
- 请帮助我理解上述代码行为。了解 void 指针和双 void 指针操作
- 在指针的帮助下交换的情况下无法生成错误
- Char 数组解释为构造函数中的 char 指针请帮助
- C++ 概念帮助,指针
- 如何在 c++ 中将包含指针变量的对象写入和读取到文件中?帮助我使用以下代码
- 在结构指针方面需要帮助
- 在下面的例子中,如何在C++中使用智能指针有帮助
- 将节点附加到C++树(参考和指针帮助)
- c++链表帮助(指针)