当我们在c ++中创建类的对象时,或者在创建类的对象时会发生什么,会调用哪些方法。
答案 0 :(得分:3)
如果没有附加信息,您应该假设调用类本身中只有一个成员函数,即构造函数。
class CheesePizza {
public:
CheesePizza() {}
};
CheesePizza barely; // will initialize by calling Foo::foo().
在许多情况下,可能会调用其他函数,例如,如果您创建必须创建临时对象的转换方案,例如指定std :: string参数并传递const char * value。
class DIYPizza {
std::string m_toppings;
public:
DIYPizza(const std::string& toppings) : m_toppings(toppings) {}
};
DIYPizza dinner("all of the toppings");
这必须从const char *参数创建一个临时的std :: string,“所有的toppings”。然后DIYPizza :: DIYPizza(std :: string)运算符可以传递给临时(rvalue),然后我们从它初始化m_str,它调用std :: string(const std :: string&)复制构造函数来初始化m_str
基本上做的是:
// create a std::string object initialized with the c-string.
std::string rvalueString = std::string("all of the toppings");
// now we have a string to pass to DIYPizza's constructor.
DIYPizza dinner(rvalueString);
但是 - 此时我们仍然只调用Foo 的一个成员函数。调用更多类成员的唯一方法是从调用的任何构造函数中调用它们。
class DinnerAtHome {
void orderPizza();
void drinkBeer();
void watchTV(); // I was going with something more brazen, but...
public:
DinnerAtHome() {
orderPizza();
drinkBeer();
watchTV();
drinkBeer();
// arrival of pizza is handled elsewhere.
}
};
现在,当你构造一个新的DinnerAtHome时,将调用5个成员函数:DinnerAtHome :: DinnerAtHome()和它所做的四个成员函数调用。
注意:“new”不是成员函数,而是global operator。
如果答案是“五”,那么面试官正在使用一个技巧问题,或者你错过了一些细微的问题。
答案 1 :(得分:1)
好的,我尝试过度回答,因为没有一次选择了答案: 当你创建一个对象时,构造函数被调用,这也涉及对成员对象的底层构造函数的调用,如果对象继承自另一个对象,你还需要调用基类的构造函数
class Foo: public Bar{
std::vector<int> indices; //default constructor for indices is called
public:
Foo(int a):Bar(a){ //you have to call constructor of Bar here
//else compiling error will occur
}
};
默认构造函数是为具有它的对象隐式调用的。当您使用“new”创建内容时,会分配第一个内存,然后在该内存之上构建对象(placement new以类似的方式工作,但内存块可能由用户在其他地方明确创建)。
请注意,在某些情况下,您不知道构造函数调用的顺序:
案例1
Obj1* myobj= new Obj1 ( new Obj2, new Obj3( new Obj4) );
在这种情况下,如果在Obj2之前或之后创建Obj4并且如果在Obj2之前或之后创建Obj3,则没有线索,只需编译器尝试选择“顺序”(可能因编译器和平台而异),这也是一个非常不安全的代码: 假设Obj2已经创建时Obj3中出现异常,那么Obj3内存将永远不会被释放(在极端情况下,您可能会发现有用的工具来解决这些问题:Hypodermic / Infectorpp)
案例2
静态/全局变量可能以不同的顺序初始化,您必须依赖特定的编译器函数来声明初始化顺序
海湾合作委员会:
void f __attribute__((constructor (N)));
还要注意“构造函数”不像其他人那样“方法”,事实上你不能在std :: function中保存构造函数,也不能用std :: bind绑定它。保存构造函数的唯一方法是使用工厂方法包装它。
如你在采访中提到的那样,这应该是5个“事物”。答案 2 :(得分:0)
如果要创建类,则意味着您正在调用该类的构造函数。如果构造函数不在您的代码中,那么编译器将添加默认构造函数。你可以覆盖默认构造函数来执行对象创建的一些任务。 对于 例: 如果要创建Person类型的对象
Person* objPerson = new Person();
这意味着您正在调用该类的Person()方法(构造函数)。
class Person {
public:
Person() {
// ...
}
};
答案 3 :(得分:0)
当构造一个新对象时,调用该类的构造函数来初始化该类的非静态成员变量(如果该类没有任何构造函数,则编译器为该类指定一个空构造函数并调用它) 。构造函数可以调用其他函数(库或用户定义的函数),但这取决于程序员在构造函数中调用的函数。此外,如果类是继承层次结构的一部分,则在实例化类的构造函数之前,编译器会调用适当的基类构造函数(访问here以获得简要说明)。
答案 4 :(得分:0)
当实例化类的对象时:类的对象所需的内存(取决于其数据成员)在堆上分配,并且对象名称存储对该内存位置的引用。堆上此内存位置的这些单独数据成员可能会也可能不会被初始化,具体取决于所调用的构造函数。
答案 5 :(得分:0)
让我们假设您的类名为CMyClass。
#include "MyClass.h"
/* GLOBAL objects */
static CMyClass g_obj("foo"); // static makes this object global to this file. you can use it
// anywhere in this file. the object resides in the data segment
// (not the heap or the stack). a string object is created prior
// to the constructor call.
int main(void)
{
....
if (theWorldEnds)
{
/* STACK */
CMyClass obj1; // this calls the constructor CMyClass(). It resides on the stack.
// this object will not exist beyond this "if" section
CMyClass obj2("MyName"); // if you have a constructor CMyClass(string&), the compiler
// constructs an object with the string "MyName" before it calls
// your constructor. so the functions called depend on which
// signature of the constructor is called.
/* HEAP */
CMyClass *obj3 = new CMyClass(); // the object resides on the heap. the pointer obj3
// doesn't exist beyond the scope of the "if" section,
// but the object does exist! if you lose the pointer,
// you'll end up with a memory leak. "new" will call
// functions to allocate memory.
}
}