【小记备忘】之C/C++ 杂记,catch,调用构造函数,内存分配,隐式转换【2013.12.11】
欢迎加入我们的QQ群,无论你是否工作,学生,只要有c / vc / c++ 编程经验,就来吧!158427611
【一】关于一般的函数传参 和 catch异常抛出传参的不同点
1.普通的参数传参有传值,传引用,static的区别;catch则没有,就算声明的cetch是传值传引用等,都会是该值的一个临时变量的一份拷贝,被抛出(因此,catch的效率比普通的函数传参低,所以最好用引用抛出,这样就只会拷贝生成临时变量,而不会再多拷贝一次了,也提高一点效率,当然传递指针是不会被catch传递的,但是并不建议catch指针。以后就明白了);
2.普通的函数传参支持隐式转换(如int转double等),catch则不支持(子类基类之间的转换除外),什么的是什么就捕获什么类型,不然就不捕获。
【注意】catch中,void *类型的catch能捕获任意类型指针异常。当然函数传参中可以强制转换。
【注意】catch的时候,不要把捕获基类的catch放在捕获子类的catch前面,因为捕获基类的catch会把子类的异常全部捕获,而使子类的catch永远没有执行;反过来放后,子类的捕获执行结束后,会继续执行基类的捕获。
【二】构造函数内调用构造函数
class Test
{
public:
int m_a;
Test(int a)
{
m_a = a;
}
Test()
{
new (this) Test(1);
}
};
如果一个类的构造函数要调用另一个构造函数 应该在调用的构造函数前 加 new (this)
因为并不是用这一构造函数来初始化当前的内存区,而是初始化了一个临时对象的内存区。
new (this) 并不申请内存。
另一种解决方法是 将共有代码封装到另一个非构造函数,避免构造函数调用构造函数。
【三】 对没有默认构造函数的类申请动态空间
class A
{
public:
A(int i){}//传参构造
};
int _tmain(int argc, _TCHAR* argv[])
{
void *i =operator new [](4 * sizeof(A));//申请4个空间的A的大小内存
A *ii = static_cast<A *>(i); //强制转换空间
ii[0] = new A(0);
ii[1] = new A(1);
ii[2] = new A(2);
ii[3] = new A(3);
operator delete[](i);
}
如果类没有无參构造函数,那么就不能像这样申请动态数组 A *a = new A[];//这样是无法编译过的
所以先申请void *空间,大小和A的空间一样,再强制转换
【四】关于类中隐式转换的危机,以及如何破解的一个方法
template<class T>
class Array {
public:
class ArraySize { // 这个类是新的
public:
ArraySize(int numElements): theSize(numElements) {}
int size() const { return theSize; }
private:
int theSize;
};
Array(int lowBound, int highBound);
Array(ArraySize size); // 注意新的声明
//Array(int size); // (1)
...
};
bool operator==( const Array<int>& lhs,
const Array<int>& rhs);
Array<int> a(10);//10可以隐式转换成Arrysize再用这个临时变量变成Arry的构造函数
Array<int> b(10);
for (int i = 0; i < 10; ++i)
if (a == b[i]) //靠 "a" 应该是 "a[i]"; 不能从b[i]隐式转换成嵌套类ArrySize 再转成Arry对象所以就不能比较 a和b[i]了//一个错误。
//如果有像(1)那样的构造函数声明,就可以调用该构造函数,将 b[i] 隐式转换成 Arry 就能和a比较了
嵌套类可以解决隐式转换问题!
欢迎加入我们的QQ群,无论你是否工作,学生,只要有c / vc / c++ 编程经验,就来吧!158427611