作者:良知犹存
转载授权以及围观->欢迎添加Wx:Allen-Iverson-me-LYN
前言:本文为C++使用过程中的一些细节知识补充,碎片化的知识.其中有韦东山老师和其他博主一些知识笔记,在此谢谢韦老师以及各博主的文章博客,受益良多.
一、多重定义会使程序进行基类调用,用virtual定义基类的程序函数,然后派生类(子类)进行虚拟函数继承调用,调用的时候内存占用以及编译执行情况是如何呢?
联编机制:联编是指一个程序自身彼此关联的一个过程,按照联编所进行的阶段不同分为静态联编和动态联编.
1.静态联编,对于一般类的成员函数(非虚函数),在编译的时候就确定好了调用哪一个。而编译时所进行的联编又称为静态束定(束定是指确定所调用的函数与执行该函数代码之间的关系).
2.动态联编,在运行过程中解决选择调用函数与执行该函数代码之间的关系,又被成为动态束定。具体为:有一个指针,指向一个虚函数表;在调用的时候通过指针找到表,调用虚函数,进而将虚函数连接到当前类下。所以试下动态联编首先要有继承性,并且要求建立子类型关系,其次,一个重要条件是虚函数,继承是动态联编的基础,虚函数是动态联编的关键.
普通继承:静态联编
虚拟继承:动态联编
一般函数名字相同返回值不同的时候只能做重载不能进行虚拟函数,但是如果返回值是本次定义的类的指针或者引用时,虚拟函数才成立。
二、虚拟析构函数,将析构函数定义为虚函数,但是需要注意,如果我们派生类分配了内存空间.但是基类的析构函数不是虚析构函数的情况下,类执行析构函数的时候只执行基类析构函数,派生类则没有,造成内存泄漏.
class D{......};
class B: public D{......};
int main(int argc, char **argv)
{
D* d = new b;
return 0;
}
using namespace std;
class Human {
private:
int a;
public:
virtual void eating(void) { cout<<"use hand to eat"<<endl; }
virtual ~Human() { cout<<"~Human()"<<endl; }
virtual Human* test(void) {
cout<<"Englishman test()"<<endl;
return this;
}
};
class Englishman : public Human {
public:
void eating(void) { cout<<"use knife to eat"<<endl; }
virtual ~Englishman() { cout<<"~Englishman()"<<endl; }
virtual Englishman* test(void) {
cout<<"Englishman test()"<<endl;
return this;
}
};
class Chinese : public Human {
public:
void eating(void) { cout<<"use chopsticks to eat"<<endl; }
virtual ~Chinese() { cout<<"~Chinese()"<<endl; }/*析构函数也应该为虚拟函数*/
virtual Chinese* test(void) {
cout<<"Chinese test()"<<endl;
return this;
}
};
void test_eating(Human h){
h.eating();
}
void test_return(Human h){
h.test();
}
int main(int argc, char **argv)
{
Human h;
Englishman e;
Chinese c;
test_return(h);
test_return(e);
test_return(c);
return 0;
}
三、动态类型转化中经常使用指针,一般不适用引用,因为引用在被转换判断的时候,实体可能不存在,引用指向也就没有意义,程序就会执行失败。
/*类的定义和上面范例定义相同,此处就不多做赘述*/
void test_eating(Human &h)
{
#if 0/*有隐患*/
Englishman &pe = reinterpret_cast<Englishman&>(h);/*静态显性强制转化*/
Chinese &pc = reinterpret_cast<Chinese&>(h);
Guangximan &pg = reinterpret_cast<Guangximan&>(h);
#else
// Englishman &pe = dynamic_cast<Englishman&>(h);/*error*/
Chinese &pc = dynamic_cast<Chinese&>(h); /*动态转换*/
Guangximan &pg = dynamic_cast<Guangximan&>(h);
#endif
h.eating();
/*想分辨哪个国家的人*/
}
void test_return(Human h)
{
h.test();
}
int main(int argc, char **argv)
{
Human h;
Guangximan g;
Englishman *pe;
pe = static_cast<Englishman*>(&h);
// Englishman *pe2 = static_cast<Englishman*>(&g);
Chinese *pc = static_cast<Chinese*>(&g);
test_eating(g);
return 0;
}
四、类与派生类之间:函数名相同,参数与返回值也同样相同的函数叫做覆写函数,函数名相同参数不同叫做重载函数。
覆写函数通常应用于子类继承父类时,重写父类中的函数,覆写的函数不能在父类中为private,否则只是相当于在子类中新写了一个函数.
C++允许在同一作用域中的某个函数和运算符指定多个定义,分别成为重载函数和重载运算符.
namespace C
{
using namespace std;
class Point
{
private:
int x;
int y;
public:
Point()
{
std::cout << "/* Point() */" << std::endl;
}
Point(int x,int y) : x(x),y(y)
{
std::cout << "/* Point(int x,int y) */" << std::endl;
}
Point(const Point& p)
{
std::cout << "Point(const Point& p)" << std::endl;
x = p.x;
y = p.y;
}
~Point()
{
std::cout << "/* ~Point() */" << std::endl;
}
int getX(){return x;}
int getY(){return y;}
int setX(int x){this->x = x;}
int setY(int y){this->y = y;}
void printInfo()
{
cout<<"("<<x<<","<<y<<")"<<endl;
}
friend Point add(Point &p1,Point &p2);
friend Point operator+(Point &p1,Point &p2);
friend Point operator++(Point &p,int a);
friend Point operator++(Point &p);
};
Point add(Point &p1,Point &p2)
{
Point n ;
n.x=(p1.x+p2.x);
n.y=(p1.y+p2.y);
return n ;
}
Point operator+(Point &p1,Point &p2)
{
cout<<"Point operator+(Point &p1,Point &p2)"<<endl;
Point n ;
n.x=(p1.x+p2.x);
n.y=(p1.y+p2.y);
return n ;
}
/*Point p(1,2); ++p 函数重载 通过参数的不一致进行区分*/
Point operator++(Point &p)
{
std::cout << "++p" << std::endl;
p.x += 1;
p.y += 1;
return p;
}
/*Point p(1,2); p++ */
Point operator++(Point &p,int a)
{
std::cout << "p++" << std::endl;
Point n;
n = p;
p.x += 1;
p.y += 1;
return n;
}
}
#include "point.h"
using namespace C;
int Person::cnt = 0; /*定义和初始化 此处并不是全局变量*/
int main(int argc,char** argv)
{
Point p1(1,2);
Point p2(2,3);
std::cout << "begin" << std::endl;
++p1;
p1.printInfo();
std::cout << "***********" << std::endl;
p2++;
p2.printInfo();
std::cout << "end" << std::endl;
return 0;
}
————————END————————
长按关注,你会得到更多信息.