我无法理解如何调用/创建复制构造函数。我的问题是否在于我如何在主要调用此问题?或者是否有某种方法需要在Animal.cpp中完成。
如果这样做,我是否可以使用Animal作为基类调用派生类的复制构造函数?
Animal.cpp
#include "Animal.h"
using namespace std;
Animal::Animal()
{
}
Animal::Animal(string s, string c,string a, string d)
{
species = s;
classification = c;
animal = a;
desc = d;
}
Animal::Animal(const Animal &obj)
{
//What should be placed in here?
}
Main.cpp的
#include <string>
#include <iostream>
#include "Animal.h"
using namespace std;
int main(){
Animal *elephant = new Animal("Straight-Tusked","Mammal","Elephant","Grazer");
Animal *elephant2 = new Animal(*elephant);
}
答案 0 :(得分:3)
在C ++中,如果可能,请始终使用成员初始化:
Animal::Animal(const string &s, const string &c,const string &a, const string &d)
: species(s), classification(c), animal(a), desc(d)
{
}
还要注意const-reference的显式传递。如果传递string s
,则会获得参数的隐式副本。编译器可能copy-elides这个,所以你不会看到任何差异,但是省略是一种可能会或可能不会发生的优化。
对于复制构造函数,从我们从Animal
类看到的内容,你可能想要这样的东西:
Animal::Animal(const Animal &obj)
: species(obj.species)
, classification(obj.classification)
, animal(obj.animal)
, desc(obj.description)
{
}
复制构造函数应通过为obj
分配适当的值来复制*this
。请注意,上面也是默认的自动生成的复制构造函数(如果不存在其他字段)。
因为上面与默认的复制构造函数基本相同,所以在C ++ 11及更高版本中,您可以告诉编译器显式生成default copy constructor:
class Animal {
Animal(const Animal &) = default;
};
正如rule-of-three(现在的五条规则)那样,您可能还需要一个复制赋值运算符。
最后,当你在某处new
时,你需要delete
该对象。 C ++不执行(内置)引用计数,也没有垃圾收集器。如果忘记delete
new
d对象,则会发生内存泄漏。
正如评论中所指出的那样,完全可以通过声明变量来声明Animal
对象
Animal a(
"Hippopotamus",
"Mammalia",
"Hippopotamus",
"from the movie"
);
当程序离开当前作用域时,将自动清除(及其析构函数)。
答案 1 :(得分:1)
虽然有一个公认的答案,我想我会在你的代码中解决你的评论
//What should be placed in here?
复制构造函数正如它的名称所描述的那样。它是一个从同一类型的另一个对象构造对象的函数。所以简短的回答是,复制构造函数中的代码是创建新对象实例的代码,使用现有实例作为构造源。
如果您自己不提供复制构造函数,编译器会创建一个复制构造函数。在编译器的复制构造函数中,实例被按位复制&#39;,这意味着该类的所有数据成员都是逐位复制的。
如果您的一个或多个数据成员是指针,则会出现问题。在按位复制中,复制实例的指针将指向与复制对象相同的对象。复制对象时,您可能希望复制构造它指向的对象。这是提供自己的拷贝构造函数的原因之一。
例如:
class Foo
{
public:
int a;
int b;
Foo() : a(0), b(0) {}
Foo(int ain, int bin) : a(ain), b(bin) {}
~Foo() {}
}
class Bar
{
double z;
Foo* foo;
public:
Bar() : z(0) , foo(new Foo) {}
Bar(double zin, Foo* fooin) : z(zin), foo(fooin) {}
// Copy constructor below
Bar(const Bar &rhs) : z(rhs.z) , foo(new Foo(rhs.foo->a, rhs.foo->b)) {}
}
Bar的复制构造函数也将构造一个新的Foo对象并指向它。 请注意,Bar的复制构造函数也可以这样完成:
Bar(const Bar &rhs) : z(rhs.z) , foo(new Foo((const Foo&)*(rhs.foo))) {}
将使用编译器的Foo默认复制构造函数。
虽然首选成员初始值设定项,但记住构造函数是函数是有用的,因此您可以使用 this 指针从复制构造函数中调用任何其他构造函数,如下所示:
Animal::Animal(const Animal &obj)
{
this->Animal(obj.s, obj.c, obj.a, obj.d);
}
请注意,以下操作无效:
Animal::Animal(const Animal &obj)
{
Animal(obj.s, obj.c, obj.a, obj.d);
}
因为它将被视为表达式并创建一个匿名对象,而不是对构造函数的函数调用(至少在我的编译器上)。