C/C++ 学习笔记:类相关

原创 2016年08月28日 15:13:48

构造和析构次数

A* p =new A[5];//  构造五次

delete[ ] p;//  析构五次

delete p;// 若不使用[ ],则析构一次。


假设 A 是一个类,像这样 A a(); 并不是表示调用构造函数创建对象,只是定义了一个函数而已。


绝不重新定义继承而来的缺省参数


若父类没有无参的构造函数,子类需要在自己的构造函数中显式调用父类的构造函数。


构造函数中可以调用虚函数

class Base {
public: 
    Base() { Function();}
    virtual void Function() { cout << "Base::Function" << endl;}
}; 
class A :public Base {
public: 
    A() { Function();} 
    virtual void Function() { cout << "A::Function" << endl;}
};

另外:这样定义一个 A 的对象, A a;  会输出

Base::Function

A::Function

 而不是

A::Function

A::Function

要知道在 Base 的构造函数中调用 Fuction 的时候,调用的是 Base 的 Function。因为此时 A 还没开始构造。



静态成员变量可被该类的所有方法访问。


子类型必须是子类继承了父类的所有可继承特性,也即公有继承,才能说是子类型,否则就只是单纯的子类



重载、重写、隐藏
1. 重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。(它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!
2. 重写(覆盖):是指子类重新定义父类虚函数的方法。其函数名、参数列表、返回值类型,所有都必须同基类中被重写的函数一致,只有函数体不同(花括号内)。(和多态真正相关
3. 隐藏:隐藏是指派生类的函数屏蔽了与其同名的基类函数。注意只要同名函数,不管参数列表是否相同,基类函数都会被隐藏。(和多态无关
重载和重写的区别

1). 范围区别:重写和被重写的函数在不同的类中,重载和被重载的函数在同一类中。

2). 参数区别:重写与被重写的函数参数列表、返回类型一定相同;重载和被重载的函数参数列表一定不同,不关心函数返回类型。

class A {
    int function(int i);
    int function(int i) const; // 第一个函数的重载
    int function(const int i);// 编译错误,这里不是重载第一个函数
};

分析

首先 int function(inti)const; 这个函数的形参表和第一个函数是不一样的,因为在类中隐含this 形参的存在这里加上 const 修饰的是 this 指针,则 this 指针的类型就变为指向const 对象的指针。因此,使用指针传参时,指向const  对象的指针和指向非const  对象的指针做形参的函数是不同的。

然后 int function(constint i); 这个函数无法重载第一个函数,因为这个函数和第一个函数对于重载来说是等价的。对于非引用或指针传参,形参是否const  是等价的,但对于引用或者指针形参来说,有无const  是不同的。

3).virtual的区别:重写的基类必须要有virtual 修饰,重载函数和被重载函数可以被virtual 修饰,也可没有。

隐藏和重写,重载的区别

1). 与重载范围不同:隐藏函数和被隐藏函数在不同类中。

2). 参数的区别:隐藏函数和被隐藏函数参数列表可以相同,也可以不同,但函数名一定同;当参数不同时,无论基类中的函数是否被virtual 修饰,基类函数都是被隐藏,而不是被重写。

总的来说:隐藏和重写,要在不同的类中,如果不满足重写,那就是隐藏

 
友元函数最后面不能加 const ,在函数后面加 const  只适用于成员函数
 
虚函数
虚函数的底层是通过虚函数表实现的。
虚函数必须是其所在类的成员函数,而不能是友元函数,也不能是静态成员函数(static

1. 直接继承

1)每一个具有虚函数的类都有 1 个虚函数表 VTABLE(如果子类有自己的虚函数,那么子类的虚表里面存放继承来的虚函数地址和自己虚函数的地址),里面按在类中声明的虚函数的顺序存放着虚函数的地址,这个虚函数表 VTABLE 是这个类的所有对象所共有的;

2)在每个具有虚函数的类的对象里面都有一个 VPTR 虚函数指针,这个指针指向它自己类的 VTABLE  的首地址,每个类的对象都有这么一种指针。

2. 虚继承

对于虚继承,若派生类有自己的虚函数,则它本身需要有一个虚指针,指向自己的虚表(虚继承的时候,子类自己的虚函数单独有个虚表,然后各个父类的的虚函数分别对应一个虚表)。另外,派生类虚继承父类时,首先要通过加入一个虚指针来指向父类,因此有可能会有两个虚指针。

类对象的大小 = 各非静态数据成员(包括父类的非静态数据成员)的总和+ vfptr指针(多继承下可能不止一个)+ vbptr指针(多继承下可能不止一个)+ 编译器额外增加的字节(对齐)。


C++开发的时候,用来做基类的类的析构函数一般都是虚函数。可是,为什么要这样做呢?
虚析构函数的作用:当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。

 

多态需要通过父类的指针或者引用来实现

如果父类里的虚函数是 private 的,子类依然可以实现多态。虽然父类这个虚函数是 private,但,父类指针或引用可以通过自己的public 方法调用这个私有的虚函数。当然,子类重写的这个虚函数并不是继承来自这个父类的,但是可以实现多态。

 
多继承问题

class A {
public:
    int x;
    A(int X) : x(X) {}
    virtual void print() {
        cout << "A" <<endl;
    }
};
class B {
public:
    int x;
    B(int X) : x(X) {}
    virtual void print() {
        cout << "B" <<endl;
    }
};
class C : public A, public B {
public:
    int x;
    C() : A(1), B(2), x(3) {}
};
 
int main() {
    C c;
    cout << c.A::x << endl;// 输出 1
    cout << c.B::x << endl;// 输出 2
    cout << c.x <<endl;// 输出 3
 
    c.print();// 这里会编译错误,歧义。因为继承了 A 和 B 的 print,无法确定调用哪个。此时,若在 C 中定义了一个 print,就可以这样使用
 
    // 虽然 C 从 A 和 B 继承了 print 函数,但是由于 A 和 B 中都有 print,所以 C 的对象访问的时候要加上 A 或者 B 的域名
    c.A::print();// 输出 A
    c.B::print();// 输出 B
    A* pA = &c;
    B* pB = &c;
    pA->print();// 输出 A
    pB->print();// 输出 B
}


在重载 “+” 运算符中参数要加const,否则,连续相加会编译出错。同理 “- * / ” 也是。
class A {
    int val;
public:
    A(int v):val(v) {}
    friend const A operator+(const A& L, const A& R) {
        A temp(L.val + R.val);
        return temp;
    }
};
A a(1), b(2), c(3);
A d = a+b+c;
因为 operator+(返回值类型是A,所以 a b 求值后返回的是一个临时变量,接着这个临时变量再与 c 相加调用operator+(),临时变量不能修改,所以需要在形参里用const 引用的形式捕获。
返回值最好加上 const,否则,(b)= c这样变态的代码也不会编译出错。同理 “- * / ” 也是。

不能被重载的操作符有

.”   “::”   “?:”   “->”   “sizeof”   “#”(预处理符号)(小窍门:带点的操作符肯定不可以重载)


版权声明:本文为博主原创文章,转载请注明出处!

相关文章推荐

C/C++及相关知识学习笔记

本文以FAQ的形式记录学习C/C++的过程。 Q:对C++比较全面的总结有哪些? A:C++面试宝典2011版。pdf下载。 Q:C++面试资料知多少? A:网站:IT公司面试手册。 Q:C++是面向...
  • bugaoni
  • bugaoni
  • 2012年12月05日 17:54
  • 368

C/C++ 学习笔记:字符串、数组相关

C/C++ 中所有字符串字面值都由编译器自动在末尾添加一个空字符,即默认以 \0 结尾。 eg:字面值 "tang"  实际上是 "tang\0",字面值"tang\0" 实际上...

C/C++ 学习笔记:字符串、数组相关

C/C++ 中所有字符串字面值都由编译器自动在末尾添加一个空字符,即默认以 \0 结尾;数组名的本质;在函数内申请空间;实现 strcpy;实现 string 类.........

C++&amp;C学习笔记

  • 2008年04月14日 18:10
  • 940KB
  • 下载

学习笔记(C/C++,汇编,操作系统)

  • 2011年03月03日 12:55
  • 7.65MB
  • 下载

C_PlusPlus学习笔记 - 3_类与对象 (C++语言程序设计【第三版】 郑莉等,清华大学出版社)

在我们熟悉的现实世界中,一切事物都是对象。对象可以是有形的,也可以是无形的。对象可以是一个个体,也可以是由诸多其他对象组成。C++支持这种抽象,将抽象后的数据和函数封装在一起,便构成C++的“类”。 ...

C++ Primer Plus 学习笔记 第五章 01 for循环 递增运算符和递减运算符 复合语句,逗号运算符 C风格字符串比较、string类字符串比较

C++ Primer Plus 学习笔记 第五章 01 for循环  递增运算符和递减运算符 复合语句,逗号运算符 C风格字符串比较、string类字符串比较 声明:本文整理自《C++ Prim...

C\C++ 程序员从零开始学习Android - 个人学习笔记(八) - java基础 - 继承、抽象类、接口、内部类(待续)

http://kb.cnblogs.com/a/2335693/ 1,继承 使用extends从一个现有类(super类)继承一个子类。可以用final修饰一个类,使其不能被继承。 子类不继...

TI DSP TMS320C66x学习笔记之TI Imglib库相关函数(四)

图像分析 一、本节提供的函数描述,通常应用于图像分析应用。 图像边界和周长函数 Boundary and perimetercomputation functions are provided as ...

Linux之ubuntu学习笔记(二):一些常用快捷键和相关命令来控制系统任务ctr+z,ctr+c,ctrl+d

fg、bg、jobs、&、ctrl + z都是跟系统任务有关的,虽然现在基本上不怎么需要用到这些命令,但学会了也是很实用的 一。& 最经常被用到    这个用在一个命令的最后,可以把这个命令放到后...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C/C++ 学习笔记:类相关
举报原因:
原因补充:

(最多只允许输入30个字)