【C/C++学院】0819-/类的成员函数与const-mutable /构造与析构/拷贝构造deletedefault以及深浅拷贝/静态成员函数成员变量类在内存的存储默认参数/友元类以及友元函数

类的成员函数与const-mutable

成员函数

Fushu.h

#pragma once
#include <iostream>
class fushu
{
public:
	int x;
	int y;
public:
	fushu();
	~fushu();
	void show();
	inline void  showall(int x, int y);//显式内联
	void   setxy(int x, int y);//编译器优化,默认隐式内联
	void show(int x, int y);
	/*
	inline void  showall(int x,int y)
	{
		//复合代码
		std::cout << (this->x = x) << (this->y = y) << std::endl;
	}
	*/
};
//内联函数原则上放在头文件,去掉inline标识符
//内联函数需要展开,(VS2013是要求放在头文件的)
void fushu::showall(int x, int y)
{
	std::cout << (this->x = x) << (this->y = y) << std::endl;
}

Fushu.cpp

#include "fushu.h"

//::前面必须是类或者命名空间

fushu::fushu()
{
	std::cout << "对象被创建" << std::endl;
}

fushu::~fushu()
{
	std::cout << "对象被销毁" << std::endl;
}
//类调用成员函数,需要明确那个类的对象调用
void fushu::show()
{
	std::cout << "show" << std::endl;
}
void   fushu::setxy(int x, int y)//编译器优化,默认隐式内联
{
	this->x = x;
	this->y = y;
	std::cout << (this->x) << (this->y) << std::endl;
}
void  fushu::show(int x, int y)
{
	std::cout << (this->x) << (this->y) << std::endl;
}

成员函数.cpp

#include <iostream>
#include "fushu.h"

void stackrun()
{
	fushu fushu1;//对象在栈上
	fushu1.show();
}

void heaprun()
{
	fushu *pfushu = new fushu;//对象在堆上
	pfushu->show();
	pfushu->showall(10, 9);
	pfushu->setxy(19, 29);
	pfushu->show(1, 2);
	//内部成员函数重载,函数指针,明确了参数,
	delete pfushu;
}

void main()
{
	heaprun();

	std::cin.get();
}

Const-mutable

Constmutalbe.h

#pragma once
#include <iostream>
class constmutable
{
public:
	int a;
	int b;
	int c;
	const int d=0;//常量是必须存在初始化
	mutable int e;//限定了不被const所限制
public:
	void setabc(int a, int b, int c)
	{
		this->a = a;
		this->b = b;
		this->c = c;
	}
	void showabc() const
	{
		//函数const,可以限定不对成员变量赋值,this->a = 10;
		//this->c = 90;
		std::cout << this->a << this->b << this->c << std::endl;
	}
	constmutable();
	~constmutable();
};

Constmutable.cpp

#include "constmutable.h"

constmutable::constmutable()
{
}

constmutable::~constmutable()
{
}

构造与析构

构造函数与赋值的区别

#include<iostream>

//所有的类默认都有一个构造函数,析构函数
//构造函数,重载,
//没有返回值,
class myclass
{
public:
	int num;
public:
	myclass()// :num(4)初始化第一种方式
	{
		//num = 10;第二种方式
		std::cout << "class create";
	}
	myclass(int data) //构造函数可以重载
	{
		std::cout << "class create  by data";
		num = data;
	}
	~myclass()
	{
		std::cout << "class delete";
	}
};

void run()
{
	//myclass myclass1(10);
	//myclass myclass1 = 101;
	//myclass *p = new myclass(102);
	myclass *p (new myclass(102));
	//p(new myclass(105));
	std::cout << (*p).num << std::endl;
	//std::cout << myclass1.num << std::endl;
}

void main1()
{
	run();

	int num = 4;
	num = 4;
	int data(4);
	//data(5);

	std::cin.get();
}

构造与析构的顺序

#include<iostream>

//系统自动给你生成了构造函数与析构函数
//被包含的,最先分配,最后释放
//包含别人的,最后分配,最先释放
class fushu
{
public:
	fushu();
	~fushu();
};

fushu::fushu()
{
	std::cout << "fushu构建" << std::endl;
}

fushu::~fushu()
{
	std::cout << "fushu销毁" << std::endl;
}

class math
{
public:
	fushu fushu1;
	math()
	{
		std::cout << "math构建" << std::endl;
	}
	~math()
	{
		std::cout << "math销毁" << std::endl;
	}
};

void go()
{
	math math1;
}

void main2()
{
	//fushu fushu1;
	go();

	std::cin.get();
}

Explicit

#include <iostream>
#include <array>

class  classobj
{
public:
	int num;
public:
	explicit  classobj(int data)
	{
		this->num = data;
		std::cout << "被构造" << num << std::endl;
	}
	//classobj()
	//{
	//	std::cout << "被构造yuan" << num << std::endl;
	//}
	~classobj()
	{
		std::cout << "被销毁" << num << std::endl;
	}
protected:
private:
};

void main()
{
	//C 语言风格的数组,构造一个数组,销毁一个数组

	classobj obj(0);//单独独有构造函数
	classobj objx[3] = { classobj(0), classobj(1), classobj(2) };//C语言风格数组构造方式
	classobj(*ppobjA)[3] = &objx; //指向数组的指针
	classobj  *pobj ( new classobj(0)) ;

	classobj * ppobj[3];//数组,每一个元素都是指针
	ppobj[0] = new classobj(0);
	ppobj[1] = new classobj(1);
	ppobj[2] = new classobj(2);	

	//classobj *p= new  classobj[10];
///	delete[]p;

	std::cin.get();

}

void main11111()
{
//	classobj  num = 5;//赋值号,类型转换
	//classobj  data(5);

	// classobj  obj;
	classobj obj(0);//创建对象必须合适的构造函数
	//classobj *p= new classobj;

	//C++ 风格数组的作用
	classobj * p = new classobj(5);
	std::array <classobj, 2 > myarray = { obj, *p };

	std::cin.get();
}

拷贝构造deletedefault以及深浅拷贝

拷贝构造

#include<iostream>

//如果声明已经定义,便不会生成
class classA
{
private:
	int a;
	int b;
public:
	//拷贝构造的规则
	classA(int x, int y)//:a(x), b(y)
	{
		//a = x;
		//b = y;
	}
	void print()
	{
		std::cout <<a << b << std::endl;
	}
};

void main12313()
{
	classA  class1(10,100);//编译器会默认生成默认的构造函数
	classA  class2(class1);//编译器会生成默认的拷贝构造函数
	class1.print();
	class2.print();//默认的拷贝构造函数
	//classA class3(4);

	std::cin.get();
}

Delete-default

//delete可以禁用默认生成的函数,禁用构造可以无法实例化
//禁用拷贝构造,可以实现禁止别人拷贝你
//default默认存在
class myclassA
{
public:
	//myclassA() = delete;//默认删除构造函数,无法实例化
	//myclassA() = default;//默认存在
	//myclassA(const 	myclassA &) = delete;//拷贝构造函数
	//myclassA(const 	myclassA &) = default;
	//=//缺省的赋值函数
	~myclassA();
};

void main211()
{
	//myclassA myclassa1;
	//myclassA myclassa2(myclassa1);
	//myclassA myclassa3 = myclassa1;//重载了=,根据类型进行判断
	//	myclassA a1;

}

深拷贝浅拷贝

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<string>

class string
{
public:
	char *p;
	int length;
	string(int num,char *str)
	{
		//获取长度,分配内存,拷贝内容
		length = num;
	    p = new char [length];
		memset(p, 0, length);//
		strcpy(p, str);
	}
	string(const string & string1)
	{
		//qian
		//this->p = string1.p;
		//	this->length = string1.length;
		//shen
		this->p = new char[string1.length];
		this->length = string1.length;
		memset(this->p, 0, this->length);//
		strcpy(this->p, string1.p);
	}
	~string()
	{
		delete[] p;//
	}
};

void main()
{
	string *pstr1 = new string(10, "hello");
	std::cout <<pstr1->p<< std::endl;
	string *pstr2 = new string(*pstr1);
	delete pstr1;
	std::cout << pstr2->p << std::endl;

	std::cin.get();
}

void main1()
{
	string str1(10, "hello");
	std::cout << str1.p << std::endl;

	string str2(str1);
	std::cout << str2.p << std::endl;

	std::cin.get();
}

静态成员函数成员变量类在内存的存储默认参数

Class与内存

#include<iostream>

class myclass
{
public:
	int num;
	int data;
	int *p;
	const int coint;
	int & myint;
	static int shu;//声明
	static const int dashu;
public:
	static void go()
	{
	}
	void run()
	{
	}
//常量,引用,必须重载构造函数初始化,
	myclass(int a, int b) :myint(a), coint(b)
	{	//引用就是共用地址,常量新开辟备份机制
		std::cout << &a << "  " << &b << std::endl;
		std::cout << &myint << "  " << &coint << std::endl;

		const int *p = &coint;//地址
		std::cout << *p << "   " << coint << std::endl;
		int *px = const_cast<int *>(p);//去掉const转换
		*px = 12;
		std::cout << coint << "  " << *px << std::endl;
	}
	~myclass()
	{
	}
};

int myclass::shu = 0;//初始化
const int myclass::dashu = 20;//常量

void  main()//尝试去掉const属性
{
	const int *px = &(myclass::dashu);
	std::cout << px << std::endl;
	int *p = const_cast<int *> (px);
	*p = 123;//静态常量区可以访问,不可以修改,
	std::cout << *px << "  " << *p << "   " << myclass::dashu;

	std::cin.get();
}

class mywindowW
{
public:
	int  #//引用,必须在构造的初始化,
	//引用今天可以引用这个人,明天引用那个人
public:
	mywindowW(int data) :num(data)
	{

	}
};

int mainrr()
{
	int data = 20;//引用必须初始化,反复赋值,类中的引用必须在构造函数初始化
	mywindowW  my1(data);
	std::cout << my1.num; //加上endl关闭输出,当作地址,否则当作变量
	int dataA = 201;
	my1.num = dataA;
	std::cout << my1.num;//加上endl关闭输出,当作地址,否则当作变量
	std::cin.get();

	return 0;
}

int mainr()
{
	int data2 = 11;

	int  data1 = 22;//引用必须初始化,反复赋值,
	int & da = data1;
	std::cout << da<< std::endl;
	da = data2;
	std::cout << da<<std::endl;

	std::cin.get();
	return 0;
}

class mywindowWW
{
public:
	const int num;
public:
	mywindowWW(int data) :num(data)
	{

	}
};

void mainconst()
{
	int int1 = 20;
	mywindowWW  mywindowWW1(int1);//初始化,常量必须构造的时候初始化
	//类的外部一旦初始化以后,不会读内存,从代码区的符号表自动生成,
	std::cout << mywindowWW1.num << std::endl;

	//mywindowWW1.num = 19;//mywindowWW1”: 不能给常量赋值

	std::cin.get();
}

void main2312312()
{
	//类中的普通成员变量
	//类名 变量名  //栈上
	//类名 *指针名 =new  类名   //堆上
	//类的静态成员  静态区
	//成员函数,静态函数都在代码区,类的函数都是共享
	//myclass myclass1(10, 9);
	//int a(5);

	//void(myclass::*p1)() = &myclass::run;
	//代码共享,所有的类对象共享对象,
	//void(*p2)() = &myclass::go;//静态函数,与对象没有关系

	//引用本质就是变量的别名,4个字节,本质是一个指针

	myclass myclass1(10, 9);

	//static const int dashu; 静态区,修改
   //

	//int a;
	//int &ra;

	std::cin.get();
}

默认参数

#include<iostream>

class goodclass
{
public:
	int num=1;//默认初始化的值,C++11特定
	const int data=90;//const,少写构造函数
public:
	static void show(goodclass good1)
	{
		std::cout << good1.num << "  " << good1.data<<std::endl;
	}
};

//类中的const默认还是可以修改,与C语言const一致
void main()
{
	goodclass good1;
	goodclass::show(good1);

	const int *px = &(good1.data);
	std::cout << px << std::endl;
	int *p = const_cast<int *> (px);
	*p = 123;
	std::cout << *px << "  " << *p << "   " << good1.data<<std::endl;
	goodclass::show(good1);

	std::cin.get();
}

友元类以及友元函数

1、为什么要引入友元函数???

在实现类之间数据共享时,减少系统开销,提高效率。具体来说:为了使其他类的成员函数直接访问该类的私有变量。 即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数。

优点:能够提高效率,表达简单、清晰

缺点:友元函数破环了封装机制,尽量不使用成员函数,除非不得已的情况下才使用友元函数。

2、什么时候使用友元函数??

1)运算符重载的某些场合需要使用友元。

2)两个类要共享数据的时候

版权声明:本博客所有文章均为原创,欢迎交流,欢迎转载;转载请勿篡改内容,并且注明出处,谢谢!

时间: 2024-10-21 03:05:41

【C/C++学院】0819-/类的成员函数与const-mutable /构造与析构/拷贝构造deletedefault以及深浅拷贝/静态成员函数成员变量类在内存的存储默认参数/友元类以及友元函数的相关文章

拷贝构造,深度拷贝,关于delete和default相关的操作,explicit,类赋初值,构造函数和析构函数,成员函数和内联函数,关于内存存储,默认参数,静态函数和普通函数,const函数,友元

 1.拷贝构造 //拷贝构造的规则,有两种方式实现初始化. //1.一个是通过在后面:a(x),b(y)的方式实现初始化. //2.第二种初始化的方式是直接在构造方法里面实现初始化. 案例如下: #include<iostream> //如果声明已经定义,边不会生成 class classA { private: int a; int b; public: //拷贝构造的规则,有两种方式实现初始化 //1.一个是通过在后面:a(x),b(y)的方式实现初始化 //2.第二种初始化的方式是直

【C/C++学院】0813-C与CPP不同以及命名空间简介/函数重载与函数默认参数/泛型auto/Newdelete

C与CPP不同以及命名空间简介 命名空间在软件设计中的作用就是为了实现迭代式开发. 命名空间的别名 #include <iostream> namespace runrunrunrun { int a(10); char *str("gogogo"); namespace run //命名空间的嵌套 { int a(9); } } namespace runrunrunrun //命名空间的拓展 { int y(5); //int a(15);重定义错误 } namespa

函数声明和函数定义中的默认参数浅析

默认参数是存在于函数的声明中,还是函数的定义中呢? 我在VS6.0和VS2008下做了如下实验,并做出了简单的总结,有不足或者不准确的地方,欢迎大家拍砖,我会及时修正相关内容. 实验一:默认参数不能同时存在于函数声明和函数定义中. #include <iostream> #include <tchar.h> using namespace std; void SetHeight(double dHeight = 183.5); int _tmain(int argc, TCHAR*

C++函数默认参数(转)

在代码中使用到了函数的默认参数,在函数的定义和实现中都填写的默认参数,结果出现了错误: 代码: 1 #ifndef FIRSTPAGE_H 2 #define FIRSTPAGE_H 3 4 #include <QWizardPage> 5 #include "ui_firstdialog.h" 6 7 class FirstPage : public Ui::FirstDialog, public QWizardPage 8 { 9 public: 10 FirstPag

重载函数和默认参数的函数

代码说事 重载的参数匹配 1 /// *重载的匹配顺序 1: 严格匹配 2: 转换匹配 2 /// *重申 : 重载的判断依据 !形参的! 个数 类型 位置 3 /// * 返回值类型不作为重载依据 4 /// * 默认参数 不能用于区分重载函数 5 6 #include <bits/stdc++.h> 7 using namespace std; 8 9 /// 转换 的匹配 10 double b; 11 void print(int a); 12 void print(char c);

c++-内联函数和函数重载和默认参数和函数指针

内联函数 C++ 内联函数是通常与类一起使用.如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方. 对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则将会继续使用旧的函数. 如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义.如果已定义的函数多于一行,编译器会忽略 inline 限定符. 在类定义中的定义的函数都是内联函数,即使没有使用 inline 说

函数的非固定参数,默认参数,参数组

默认参数: 也可以给默认参数赋值,这个时候就取代了默认的值了: 默认参数的特点:调用函数的时候,默认参数非必须传递: 作用:1.自定义安装软件,默认安装值: 2.连接数据库的参数:比如默认端口号3306 参数组: *args,这个就是参数组,前面有一个星号*,后面可以跟任意字母,定义一个参数组. 接受多个实参,然后把实参放到一个元祖里去.下面的列表作为实参,也是可以的.不过都是转换为元祖. 也可以这么应用,如下图: 如果传输字典实参到函数,可以如下:**kwargs,两个*.把N个关键字参数,转

内联函数、默认参数和函数占位参数

内联函数 定义:内联函数从源代码层看,有函数的结构,而在编译后,却不具备函数的性质.内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处.编译时,类似宏替换,使用函数体替换调用处的函数名.一般在代码中用inline修饰,但是能否形成内联函数,需要看编译器对该函数定义的具体处理. C++中的const常量可以替代宏常数定义,如: const int A = 3; ? #define A 3 C++中是否有解决方案替代宏代码片段呢?(替代宏代码片段就可以避免宏的副作用!) C++

函数重载和默认参数

区别一是参数类型不同,二是参数个数不同 仅有函数返回值不同也是区分不了重载函数的 1 #include <iostream> 2 using namespace std; 3 4 void go(int i, double db)//参数的个数,参数的类型不同,顺序不同,与返回值无关 5 { 6 7 } 8 9 void go(double db, int i) 10 { 11 12 } 13 14 void main() 15 { 16 17 system("pause"