类型转换,类与类之间的转换,继承关系,继承与静态变量,子类父类重名,多继承,虚基类

简介:  常量的基本类型转换,例如:int num(10.8),这种方式是隐式转换。 通过函数的构造函数实现转换。 类类转换函数,当构造函数不能将类型转换成基本类型时。所以就有了类类转换函数,通过这种方式。 案例: #include <iostream>class fushu{public: //通过加

  1. 常量的基本类型转换,例如:int num(10.8),这种方式是隐式转换。

  2. 通过函数的构造函数实现转换。

  3. 类类转换函数,当构造函数不能将类型转换成基本类型时。所以就有了类类转换函数,通过这种方式。

案例:



#include <iostream>

class fushu
{
public:
	//通过加explicit的这种方式避免隐式转换,避免引发歧义
	explicit fushu(int num)
	{
		x = num;
		y = num;
	}
	void print()
	{
		std::cout << x << "+" << y << std::endl;
	}
	//下面对这个声进行明实现,重载int,这里是类型转换函数
	operator int();
	
	//不支持友元,仅仅支持成员函数
	operator double()
	{
		return (double)(x + y);
	}
protected:
private:
	int x;
	int y;
};

//下面是:类类之间的转换函数
fushu::operator int()
{
	return x * y;
}

void main()
{
	int num(100.9);
	fushu fushu1(num);//构造函数
	fushu1.print();
	//下满如果不带(int)将报错误提示
	//类型转换可以把一个自定义类型当作基本数据类型来计算
	int data = (int)fushu1 + 10;//这一句的运行结果是:10000+10
	std::cout << data << std::endl;
	std::cin.get();
}

//转换有两种方式:1、赋值;2.使用()调用构造进行转换
void main2()
{
	int num(100.9); //这里调用了int类型的构造
	fushu fushu1(num);  //构造函数

	int data(fushu1);//转换,调用:fushu::operator int()
	std::cout << data << std::endl;
	//通过下面几句走类类转换函数(fushu::operator int())data2-->data5,下面几种方式得到到的结果都是10000
	int data2 = fushu1; 
	std::cout << data2 << std::endl;
	int data3 = (int)fushu1;
	std::cout << data3 << std::endl;
	int data4 = int(fushu1);
	std::cout << data4 << std::endl;
	int data5 = (int(fushu1));
	std::cout << data5 << std::endl;
}

void main1()
{
	//基本数据类型转换,这里是隐式类型与显式转换,是否带有类型转换符
	int num(10.8);

	//调用构造函数,调用explicit fushu(int num)这个构造函数
	fushu fushu1 = (fushu)10.8;
	//调用之后的结果是:10
	fushu1.print();   
	//通过static_cast的方式进行类型转换,这种方式同样走了构造函数
	fushu fushu2 = static_cast<fushu>(12.8);
	fushu2.print();   //调用之后的结果是:10 
	
	fushu fushu3 = (fushu)10;//构造函数
	//因为一个类不可能转换成为int类型的,所以找重载int的fushu::operator int()
	int numA = fushu3;  //这里调用之后的结果是100
	std::cout << numA << std::endl;

	std::cin.get();
}

4.类与类之间的类型转换

#include<iostream>

class mianji
{
public:
	//通过友元,让fushu这个类可以调用这两个类的变量
	friend class fushu;
	mianji()
	{
		this->cx = 0;
		this->cy = 0;
	}
	void setxy(int a,int b)
	{
		this->cx = a;
		this->cy = b;
	}
private:
	int cx;
	int cy;
};

class fushu
{
public:
	//友元可以访问私有变量
	friend class mianji;
	fushu(mianji mianji1)
	{
		this->x = mianji1.cx;
		this->y = mianji1.cy;
	}
	void print()
	{
		std::cout << x << "+" << y << std::endl;
	}
	//使用operator+类的方式进行转换,类与类之间的类型转换
	operator mianji()
	{
		mianji temp;
		temp.cx = x;
		temp.cy = y;
		return temp;
	}
private:
	int x;
	int y;
};

void main()
{
	mianji mianji1;  //这里调用了
	//这里调用了fushu的有参构造函数
	fushu fushu1 = (fushu)mianji1;  
	fushu1.print();   //结果:0+0

	fushu fushu2(mianji1);//调用了构造函数
	fushu2.print();  //结果:0+0

	mianji mianji2;
	//设置x,y的值
	mianji2.setxy(10, 20);

	fushu1 = mianji2;
	fushu1.print(); //结果:10+20

	std::cin.get();
}

5.类和类之间的关系:

案例:

#include "mainwindow.h"
#include <QApplication>

#include<stdlib.h>

//第一种关系,某一个类作为某一个类的部件
class mywindow
{
public:
    MainWindow w;//这时一种包含关系
};

class show
{
public:
    //部分的使用一个类,调用一个类
    void showwindow(MainWindow  & w)
    {
        w.show();
    }
};

//继承是通过加上:的方式实现
class newwindow:public MainWindow
{
public:
    //增强一个功能
    void run(char *str)
    {
        system(str);
    }
};

//测试继承
int mainA(int argc, char *argv[])
{
    QApplication a(argc, argv);
    newwindow new1;
    new1.show();

    //运行的结果是显示了计算器窗口
    new1.run("calc");

    return a.exec();
}

//通过包含的方式进行调用一个类
int main(int argc,char *argv[])
{
    QApplication a(argc,argv);
    
    mywindow my1;
    show show1;
    show1.showwindow(my1.w);
    
    return a.exec();
}

6.继承之间的关系

A:共有(public)继承 à可以无限传承,原来是共有的public继承之后仍然共有,私有的还是私有的。

B:私有(private)继承,只能继承一代,一代之后不可以继承了。不管父类里共有的还是私有的,都变成私有的了。

C:保护(protected)继承,共有成员全部变成了保护成员,保护成员不发生变化,可以无限传承。

创建三个类来描述这三种关系:

创建人类,代码如下:

头文件ren.h


#pragma once
class ren
{
public:
	ren();
	~ren();
	long long selfnum;
private:
	char *name;
	bool isman;
protected:
	int money;
	int house;
};
//设计一个类,可以无限传承美德,私有资产
//公有继承  ->无限传承,公有,保护不发生 70%

//只能继承一代,
//私有继承 ->传一代就断了,公有,私有都变成私有  


//保护继承
//保护继承->公有成员全部变成保护成员  保护成员不发生变化,可以无限传承

ren.cpp
#include "ren.h"
ren::ren()
{
}

ren::~ren()
{
}

创建月光族

yueguang.h

#pragma once
#include "ren.h"
class yueguang:public ren  //这里用月光族来模拟共有的特征
{
public:
	yueguang();
	~yueguang();
};
yueguang.cpp
#include "yueguang.h"
yueguang::yueguang()
{
}
yueguang::~yueguang()
{
}

创建啃老族(父类的东西都变成自己的了,并且子辈没有东西):

kenlao.h

#pragma once
#include "ren.h"
class kenlao:private ren  //模拟私有继承
{
public:
	kenlao();
	~kenlao();
};


kenlao.cpp
#include "kenlao.h"

kenlao::kenlao()
{
}

kenlao::~kenlao()
{
}

模拟可传承的特征:

chuancheng.h

#pragma once
#include "ren.h"
class chuancheng:protected ren  //模拟可供传承的类
{
public:
	chuancheng();
	~chuancheng();
};

chuancheng.cpp
#include "chuancheng.h"

chuancheng::chuancheng()
{
}

chuancheng::~chuancheng()
{
}

7. //子类的内部可以访问父类的被保护的num,通过::num的方式进行调用

//此外还可以通过这种方式访问父类的方法。如果不写这个就是调用本类的方法

std::cout <<(this->coder::num) << std::endl;

通过另外一个案例说明继承的三种关系:

coder.h

#pragma once

#include<iostream> //加了这一句之后std::cout才可以用
class coder
{
private:
	char *str;
public:
	coder();
	~coder();
	void girlfriend();
	void coding();
protected:
	int num;
};
coder.cpp
#include "coder.h"

coder::coder()
{
	std::cout << "coder create" << std::endl;
	str = "锄禾日当午";
	num = 100;
}

coder::~coder()
{
	std::cout << "coder delete" << std::endl;
}

void  coder::girlfriend()
{

	std::cout << "一般都会写代码,可以创建一个对象,可是没有对象" << std::endl;
}

void  coder::coding()
{

	std::cout << "加班加点熬夜" << std::endl;
}

公有继承

cppcoder.h


#pragma once
#include "coder.h"

//使用public继承的时候
//父类的私有成员,不可以访问
//父类的保护成员,共有成员都可以访问
//共有继承,不影响保护成员,共有成员属性变化
class cppcoder:public coder
{
public:
	cppcoder();
	~cppcoder();
	void coding();
	void ui();
};
cppcoder.cpp
#include "cppcoder.h"


cppcoder::cppcoder()
{
	std::cout << "cpp coder create" << std::endl;
}

cppcoder::~cppcoder()
{
	std::cout << "  cpp  coder delete" << std::endl;
}

void cppcoder::ui()
{
	std::cout << "QT真蛋疼" << std::endl;
	//子类的内部可以访问父类的被保护的num,通过::num的方式进行调用
	//此外还可以通过这种方式访问父类的方法。如果不写这个就是调用本类的方法
	std::cout << (this->coder::num) << std::endl;
}

void cppcoder::coding()
{
	std::cout << "CPP真蛋疼" << std::endl;
}
保护继承:
ccoder.h
#pragma once
#include "coder.h"

//父类的私有成员,不可以被继承
//父类的保护成员,共有成员内部可以访问

//protected继承的时候:保护成员,共有成员都会变成保护成员
class ccoder:protected coder
{
public:
	ccoder();
	~ccoder();
};
ccoder.cpp
#include "ccoder.h"


ccoder::ccoder()
{
}


ccoder::~ccoder()
{
}

私有继承
javacoder.h
#pragma once
#include "coder.h"

//父类的私有成员,不可以访问
//使用private继承之后,父类的保护成员,共有成员内部可以访问
//私有继承,共有成员,保护成员都变成私有成员
class javacoder:private coder
{
public:
	javacoder();
	~javacoder();
};

javacoder.cpp
#include "javacoder.h"


javacoder::javacoder()
{
	//父类的被进程的变量可以在子类中可以访问,类外不可以被访问
	this->num = 100;
}


javacoder::~javacoder()
{
}
主函数
#include<iostream>
#include "coder.h"
#include "cppcoder.h"
#include "javacoder.h"

void main1()
{
	//通过new关键字创建一个类的指针
	javacoder *pjava = new javacoder;
	//这时候的结果是:coder create,说明要调用父类的构造函数
	std::cin.get();
}

void main2()
{
	cppcoder *ptansheng = new cppcoder;
	coder *pcode = new coder;
	ptansheng->ui();

	std::cin.get();

	//运行结果:
	//coder create
	//cpp coder create
	//coder create
	//QT真蛋疼
	//100
}

void main3()
{
	//父类的指针,接受子类指针的地址
	coder *pcode = new cppcoder;
	pcode->coding();

	//通过reinterpret_cast进行类型转换
	cppcoder *pcppcoder = reinterpret_cast<cppcoder *>(pcode);
	pcppcoder->coding();
	//通过下面的方式实现获得指针类型
	std::cout << typeid(pcode).name() << std::endl;
	std::cout << typeid(pcppcoder).name() << std::endl;

	std::cin.get();
	//运行结果:
	//coder create
	//cpp coder create
	//加班加点熬夜
	//CPP真蛋疼
	//class coder *
	//class cppcoder *
}

void main()
{
	cppcoder *ptansheng = new cppcoder;
	ptansheng->girlfriend();
	ptansheng->ui();
	//当子类与父类中函数同名的时候,会覆盖父类中的函数
	ptansheng->coding();
	//每一个子类都会生成一个默认的父类对象
	//调用父类的同名方法可以通过下面的方式实现
	ptansheng->coder::coding();

	delete ptansheng;

	std::cin.get();
	//运行结果:
	//coder create
	//cpp coder create
	//一般都会写代码,可以创建一个对象,可是没有对象
	//QT真蛋疼
	//100
	//CPP真蛋疼
	//加班加点熬夜
	//  cpp coder delete
	//coder delete
}

8.子类父类重名问题

#include<iostream>

class father
{
public:
	int num;
	void print()
	{
		std::cout << num << std::endl;
	}
	father()
	{
		num = 99;
	}
};

class son :public father
{
public:
	int num;
	void print()
	{
		std::cout << num << std::endl;
	}
	//子类覆盖父类
	son()
	{
		num = 89;
	}
};


void main()
{
	son *pson = new son;
	pson->print();
	//第一种方式调用父类中的方法
	pson->father::print();

	//第二种方式调用父类中的方法,将子类转换强转成为父类的指针
	father *p = reinterpret_cast<father *>(pson);
	p->print();

	std::cin.get();
}
运行结果:
89
99
99

9.基类的初始化

#include<iostream>

class myclass
{
public:
	myclass() :x(0)
	{
		//x = 0;
		std::cout << "myclass  init without num" << std::endl;
	}
	myclass(int num) :x(num)
	{
		//x = num;
		std::cout << "myclass init with num" << std::endl;
	}
protected:
private:
	int x;
};

class myziclass :public myclass
{
public:
	myziclass()
	{
		std::cout << "myziclass  init without num" << std::endl;
	}
	//第一个初始化的是父类,第二个,第三个是初始化本类的x,y
	myziclass(int num) :myclass(num), x(num + 1), y(num + 2)
	{

		std::cout << "myziclass  init with num" << std::endl;
	}
	int x;
	int y;
};

void main()
{
	//指定构造函数
	myziclass *p = new myziclass(10);
	std::cin.get();
}

10.简单单继承的案例

#include <iostream>
#include<math.h>

class dian
{
public:
	friend class xian;
	dian(int a, int b, int c) :x(a), y(b), z(c)
	{
	}
	void print()
	{
		std::cout << "x=" << x << ",y=" << y << ",z=" << z << std::endl;
	}
private:
	int x;
	int y;
	int z;
};

//继承没有意义,包含
class xian
{
public:
	xian(dian dianx, dian diany) :dian1(dianx), dian2(diany)
	{
	}
	double getlength()
	{
		double length = 0;
		length = sqrt((dian1.x - dian2.x)*(dian1.x - dian2.x) + (dian1.y - dian2.y)*(dian1.y - dian2.y) + (dian1.z - dian2.z)*(dian1.z - dian2.z));

		return length;
	}
	dian dian1;
	dian dian2;
protected:
private:
};

class yuan :public xian
{
public:
	yuan(dian dianx, dian diany) :xian(dianx, diany)
	{
	}

	double getmianji()
	{
		return 3.1415926* (this->getlength())*(this->getlength());
	}

	double zhouchang()
	{
		return 3.1415926 * 2 * (this->getlength());
	}
};

class qiu :public yuan
{
public:
	qiu(dian dian1, dian dian2) :yuan(dian1, dian2)
	{
	}

	double getmianji()
	{
		return 3.1415926* (this->getlength())*(this->getlength()) * 4;
	}

	double gettiji()
	{
		return 4 / 3.0*3.1415926* (this->getlength())* (this->getlength())* (this->getlength());
	}
};

void main()
{
	dian dian1(0, 0, 1);
	dian dian2(0, 0, 6);
	dian1.print();
	dian2.print();
	xian xian1(dian1, dian2);
	std::cout << xian1.getlength() << std::endl;
	yuan yuan1(dian1, dian2);
	std::cout << yuan1.getmianji() << std::endl;
	std::cout << yuan1.zhouchang() << std::endl;
	qiu qiu1(dian1, dian2);

	std::cout << qiu1.gettiji() << std::endl;
	std::cout << qiu1.getmianji() << std::endl;

	std::cin.get();
}

11.继承与静态变量

#include<iostream>

class myclass
{
public:
	int data;
	static int num;//声明静态变量存在
	myclass()
	{
		num++;//共享,统计对象的数目
	}
	static void print()
	{
		//this->data;//静态函数无法使用this指针
		//data = 10;
		std::cout << num << std::endl;
	}

};

int myclass::num = 0;//静态变量初始化

//private私有继承,无法传承到下一代
class ziclass :protected myclass
{
	void run()
	{
		this->print();
		this->num;
	}


};

class sunclass :protected  ziclass
{


	void goandrun()
	{
		this->ziclass::myclass::print();
	}

};

void main()
{
	ziclass *p = new ziclass;
	ziclass z1;
	sunclass *ps = new sunclass;
	//int a;
	//p->num;           //这种方式同样不行,说明使用protected的之后,不可以再使用了
	//p->print();
	//p->myclass::num;  //这里不能使用,因为ziclass使用protected从class继承
	//p->myclass::print();
	//ps->print();
	//ps->ziclass::myclass::print();

	std::cin.get();
}

12.继承QT中的QLabel,并且增强其功能,创建一个QTGUI项目,修改main.cpp.

#include<QApplication>
#include<QLabel>
#include<stdlib.h>

class mylabel:public QLabel
{
public:
    mylabel(char *str):QLabel(str)
    {
    }
    void run(char *str)
    {
        system(str);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    mylabel my1("12345ABC");
    my1.show();
    my1.run("notepad");

    return a.exec();
}

13:多继承,将很多东西的东西集成在一起,多继承案例如下:

#include <iostream>
#include<stdlib.h>

class A{};

class B{};

class myclass1
{
public:
	void run(char *str)
	{
		system(str);
	}
	myclass1()
	{
		std::cout << "myclass1 is create" << std::endl;
	}
	~myclass1()
	{
		std::cout << "myclass1 is delete" << std::endl;
	}
};

class myclass2
{
public:
	int add(int a, int b)
	{
		return a + b;
	}
	myclass2()
	{
		std::cout << "myclass2 is create" << std::endl;
	}
	~myclass2()
	{
		std::cout << "myclass2 is delete" << std::endl;
	}
};

class myclass :public myclass1, public myclass2, public A, public B
{
public:
	void print(char *str)
	{
		std::cout << str << std::endl;
	}
	myclass()
	{
		std::cout << "myclass is create" << std::endl;
	}
	~myclass()
	{
		std::cout << "myclass is delete" << std::endl;
	}
};

void main()
{
	myclass *pmy1 = new myclass;
	delete pmy1;

	myclass my1;
	my1.run("tasklist");
	my1.myclass1::run("ipconfig");
	std::cout << my1.add(10, 20) << std::endl;
	std::cout << my1.myclass2::add(19, 20) << std::endl;
	my1.print("12345");

	std::cin.get();
}

14.为了在创建类的时候不多次创建父类,使用虚基类技术,也就是说加上virtual关键字,案例如下:

#include<iostream>

class obj
{
public:
	int num;
	obj(int data) :num(data)
	{
		std::cout << "obj  create\n";
	}
	obj()
	{
		num = 0;
		std::cout << "obj create\n";
	}
	~obj()
	{
		std::cout << "obj delete\n";
	}
};

//下面使用了virtual(虚基类的)
class Aobj :virtual public obj
{
public:
	Aobj(int data) :obj(data)
	{
		std::cout << "Aobj create\n";
	}
	~Aobj()
	{
		std::cout << "Aobj delete\n";
	}
};

//多个类公共继承一个类的时候,为了避免重复生成父类,加上virtual
class  Bobj : virtual public obj
{
public:
	Bobj(int data) :obj(data)
	{
		std::cout << "Bobj  create\n";
	}
	~Bobj()
	{
		std::cout << "Bobj  delete\n";
	}
};

class ABobj :public Aobj, public Bobj
{
public:
	ABobj(int x, int y) :Aobj(x), Bobj(y)
	{
		std::cout << "ABobj  create\n";
	}

	ABobj(int z) :Aobj(z), Bobj(z)
	{
		std::cout << "ABobj  create\n";
	}

	~ABobj()
	{
		std::cout << "ABobj  delete\n";
	}
};

void main()
{
	ABobj *p = new ABobj(10);
	std::cout << p->Aobj::obj::num << "\n";
	std::cout << p->Bobj::obj::num << "\n";

	delete p;
	std::cin.get();
}

15QT中的多继承实现

#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
#include <QLabel>

class zajiao :public MainWindow,public QLabel,public QPushButton
{
public:
    zajiao(char *str):QLabel(str),QPushButton(str)
    {
        this->MainWindow::setWindowTitle(str);
    }
    ~zajiao()
    {}
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    zajiao zajiao1("ABCDEF12345");
    zajiao1.QPushButton::show();
    zajiao1.QPushButton::move(0,0);
    zajiao1.QLabel::show();

    zajiao1.MainWindow::show();

    return a.exec();
}










 


















目录
相关文章
|
1月前
|
C++
c++继承类型与多继承
c++继承类型与多继承
18 0
|
4月前
|
设计模式 Java 编译器
面向对象编程中的继承与多态:深入理解父类引用指向子类实例
面向对象编程中的继承与多态:深入理解父类引用指向子类实例
|
5月前
|
存储 编译器 程序员
【C++】类与对象(一)类的定义 访问限定符 类的实例化 this指针
【C++】类与对象(一)类的定义 访问限定符 类的实例化 this指针
|
7月前
|
C#
C# 继承类中(父类与子类)构造函数的调用顺序
C# 继承类中(父类与子类)构造函数的调用顺序
|
16天前
|
存储 编译器 程序员
【C++】类和对象①(什么是面向对象 | 类的定义 | 类的访问限定符及封装 | 类的作用域和实例化 | 类对象的存储方式 | this指针)
【C++】类和对象①(什么是面向对象 | 类的定义 | 类的访问限定符及封装 | 类的作用域和实例化 | 类对象的存储方式 | this指针)
|
3月前
|
C++
C++ 类中静态成员和静态成员函数的继承覆盖
C++ 类中静态成员和静态成员函数的继承覆盖
25 0
|
安全 程序员 C++
【C++要笑着学】继承 | 子类默认成员函数 | 单继承与多继承 | 钻石继承 | 虚拟继承 | 继承和组合(一)
本系列 C++ 教学博客的基础知识已经告一段落了,下面的章节我会先把面向对象三大特性讲完,然后穿插一些数据结构的教学以方便我们继续讲解 STL 的 map 和 set。对于面向对象三大特性 —— 封装、继承、多态,我们已经在之前讲解过封装了,本章将开始讲解继承,详细探讨多继承引发的钻石继承问题,并用虚继承解决钻石继承问题。阅读本章需要掌握访问限定符以及默认成员函数的知识,如果阅读过程中感到有些许生疏建议先去复习一下。
73 0
【C++要笑着学】继承 | 子类默认成员函数 | 单继承与多继承 | 钻石继承 | 虚拟继承 | 继承和组合(一)
|
Java 编译器 C++
【C++要笑着学】继承 | 子类默认成员函数 | 单继承与多继承 | 钻石继承 | 虚拟继承 | 继承和组合(二)
本系列 C++ 教学博客的基础知识已经告一段落了,下面的章节我会先把面向对象三大特性讲完,然后穿插一些数据结构的教学以方便我们继续讲解 STL 的 map 和 set。对于面向对象三大特性 —— 封装、继承、多态,我们已经在之前讲解过封装了,本章将开始讲解继承,详细探讨多继承引发的钻石继承问题,并用虚继承解决钻石继承问题。阅读本章需要掌握访问限定符以及默认成员函数的知识,如果阅读过程中感到有些许生疏建议先去复习一下。
118 0
【C++要笑着学】继承 | 子类默认成员函数 | 单继承与多继承 | 钻石继承 | 虚拟继承 | 继承和组合(二)
【C++要笑着学】多态 | 重写(覆盖) | 协变构多态 | 父虚子非虚也构多态 | final与override关键字(C++11) | 抽象类 | 纯虚函数 | 抽象类指针
本章我们继续讲解面向对象三大特性,上一章我们讲解了继承,本章我们讲解多态。从多态的概念一步步讲解,介绍构成多态的必要条件和两个例外。还会顺带讲解一下 C++11 更新的两个和多态有关系的关键字 final 和 override。上一章我们讲解了虚函数,本章会先补充纯虚函数的概念,然后再引入抽象类的概念。本章我们只学习C++多态的基础知识,至于多态的原理(VTBL、决议等)的难度相对较大,我们单独放到下一章去做专门讲解。
202 0
【C++要笑着学】多态 | 重写(覆盖) | 协变构多态 | 父虚子非虚也构多态 | final与override关键字(C++11) | 抽象类 | 纯虚函数 | 抽象类指针
|
存储 设计模式 安全
如何理解子类对象赋值给父类(深入理解动态绑定、静态绑定)
如何理解子类对象赋值给父类(深入理解动态绑定、静态绑定)
如何理解子类对象赋值给父类(深入理解动态绑定、静态绑定)