c++语法基础,构造函数,析构函数,命名空间,

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liudao7994/article/details/81980738

C++ 以前学校的时候写过. 开始写代码了.

通过案例学习c++.

visual studio 下
面向对象的语言.怎么写一个对象

  1. 创建一个空项目
  2. c++ 一般情况下 头文件和源文件分开,所以 右键项目在文件资源管理器中打开文件夹,新建两个文件夹include,src.用于存放头文件和源文件
  3. 回到项目右键头文件->新建项->位置->选择刚才创建的include文件夹->新建 Dog.h(# pragme once 这个宏代表只引用一次, )
  4. 右键源文件->新建项->位置->选择刚才创建的src文件夹->新建Dog.cpp
  5. 右键项目 -> 属性 -> 常规 -> c/c++ 常规 -> 附加包的目录 -> 编辑 -> 新建 找到include文件夹. 应用 .
  6. Dog.h 新建头文件
  7. 总共三个文件 Dog.h头文件 Dog.cpp, cpp文件 main.cpp

例子1 构造函数 析构函数 命名空间

Dog.h


class Dog
{
public:
	Dog();//构造函数 (malloc)
	~Dog();//析构函数 释放在构造函数里面动态申请的内存 (free)

	void setAge(int age);
	int getAge();
	void setName(char *name);
	char* getName();
private:
	int age;
	char *name;
};


dog.cpp

#include <Dog.h>
#include <iostream>
//c++ 标准库的命名空间
using namespace std;

Dog::Dog(){
	cout << "构造函数 Dog" << this << endl;
}

Dog::~Dog()	{
	cout << "析构函数   Dog" << this << endl;
	
}

void Dog::setAge(int age){
	cout << "dog setAge age " << age << endl;
	this ->age = age;

}
int Dog::getAge(){
	return this->age;
}
void Dog::setName(char *name){
	cout << "dog setName name " << name  << endl;
	this->name = name;
}
char* Dog::getName(){
	return this->name;
}

main.cpp

#include <Dog.h>
#include <iostream>

using namespace std;


void fun(){

	Dog dog;//局部变量

	dog.setAge(5);
	dog.setName("jumper");
	cout << "dog age " << dog.getAge() << endl;
	cout << "dog name " << dog.getName() << endl;

}

void main(){

	fun();
	system("pause");

}

运行结果:
mark

分析下:
创建了一个Dog类 给Dog 设置了年龄和名字 ,设置的时候打印一次,然后在主函数里面调用再打印一次年龄和名字. 并且打印了构造函数和析构函数的地址 .

为什么会调用析构函数?

因为Dog 声明的时候是局部变量, 调用结束后会回收就会调用析构函数.

  • Dog(); 构造函数 用于初始化一些东西
    ~Dog(); 析构函数 对象所在的函数已调用完毕时,系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。

  • Dog::Dog() 代表的意思 是Dog()这个方法 是Dog这个类里面的 .作用域限定符,当在类体中直接定义函数时,不需要在函数名字的前面加上类名,但是在类体外实现函数定义的时候,必须加上类名并且加上作用域限定符。Student::Display();

  • 命名空间 //c++ 标准库的命名空间
    using namespace std;
    如果不加命名空间打印

std::cout << "构造函数 Dog" << std::endl;

如果加了命名空间

	cout << "析构函数   Dog" << endl;
  • << 是输出流

自定义命名空间

  • 创建自己的命名空间 有点类似java的包 可以区分是自己的类还是其他人创建的类.
namespace NSP_A {
	struct MyStudent
	{
		int age;
	};
}

//使用 
	NSP_A::MyStudent t;
	t.age = 18;

	using NSP_A::MyStudent;
	
	MyStudent t2;
	t2.age = 16;

===

例子2 值传递 引用传递.

这个东西 我以前搞过. 比较熟悉.

说白了 写个方法把对象传过去后改变值, 并不会实际改变原始的值,只有传递引用过去才会改变原始的值.

值传递

#include <Dog.h>
#include <iostream>

using namespace std;


void fun(){

	Dog dog;//局部变量

	dog.setAge(5);
	dog.setName("jumper");
	cout << "dog age " << dog.getAge() << endl;
	cout << "dog name " << dog.getName() << endl;

}

void setFunValue(Dog dog){
	dog.setAge(10);
	dog.setName("小白");
	cout << "setFunValue age " << dog.getAge() << endl;
	cout << "setFunValue name " << dog.getName() << endl;

}

void main(){

	//fun();
	Dog dog;
	dog.setAge(2);
	dog.setName("小黑");
	cout << "main dog age " << dog.getAge() << endl;
	cout << "main dog name " << dog.getName() << endl;

	setFunValue(dog);

	cout << "main dog age " << dog.getAge() << endl;
	cout << "main dog name " << dog.getName() << endl;
	system("pause");

}

结果:
mark
可以看到

构造函数 Dog00FFFD78
dog setAge age 2

dog setName name 小黑
main dog age 2
main dog name 小黑

dog setAge age 10
dog setName name 小白

setFunValue age 10
setFunValue name 小白

析构函数   Dog00FFFC9C

main dog age 2
main dog name 小黑

请按任意键继续. . .

并没有改变 因为传递的是值 被回收了

传递引用

在上面的基础上加一个地址符 &

#include <Dog.h>
#include <iostream>

using namespace std;


void fun(){

	Dog dog;//局部变量

	dog.setAge(5);
	dog.setName("jumper");
	cout << "dog age " << dog.getAge() << endl;
	cout << "dog name " << dog.getName() << endl;

}

//void setFunValue(Dog dog){
//	dog.setAge(10);
//	dog.setName("小白");
//	cout << "setFunValue age " << dog.getAge() << endl;
//	cout << "setFunValue name " << dog.getName() << endl;
//
//}
void setFunValue(Dog &dog){
	dog.setAge(10);
	dog.setName("小白");
	cout << "setFunValue age " << dog.getAge() << endl;
	cout << "setFunValue name " << dog.getName() << endl;

}
void main(){

	//fun();
	Dog dog;
	dog.setAge(2);
	dog.setName("小黑");
	cout << "main dog age " << dog.getAge() << endl;
	cout << "main dog name " << dog.getName() << endl;

	setFunValue(dog);

	cout << "main dog age " << dog.getAge() << endl;
	cout << "main dog name " << dog.getName() << endl;
	system("pause");

}

结果:

mark

解析:

构造函数 Dog00AFF760
dog setAge age 2
dog setName name 小黑
main dog age 2
main dog name 小黑
dog setAge age 10
dog setName name 小白
setFunValue age 10
setFunValue name 小白
main dog age 10
main dog name 小白
请按任意键继续. . .

可以看到修改成功 因为使用了引用

例子3 给属性默认赋值

Dog.cpp 中

#include <Dog.h>
#include <iostream>
//c++ 标准库的命名空间
using namespace std;

Dog::Dog():name("旺财"),age(3){
	cout << "构造函数 Dog" << this << endl;
}

Dog::~Dog()	{
	cout << "析构函数   Dog" << this << endl;
	
}

void Dog::setAge(int age){
	cout << "dog setAge age " << age << endl;
	this ->age = age;

}
int Dog::getAge(){
	return this->age;
}
void Dog::setName(char *name){
	cout << "dog setName name " << name  << endl;
	this->name = name;
}
char* Dog::getName(){
	return this->name;
}

打印结果

构造函数 Dog008FF9E4
main dog age 3
main dog name 旺财
dog setAge age 10
dog setName name 小白
setFunValue age 10
setFunValue name 小白
main dog age 10
main dog name 小白
请按任意键继续. . .

可以看到 默认就给附上初始值了,实际上在main 中调用 Dog dog 的时候就初始化了 ,因为调用构造函数了.

例子4 带参数的构造函数, 对象和指针

Dog.h 头文件:


class Dog
{
public:
	//Dog();//构造函数 (malloc)
	~Dog();//析构函数 释放在构造函数里面动态申请的内存 (free)
	Dog(int age, char *name);//带参数的构造函数


	void setAge(int age);
	int getAge(); 
	void setName(char *name);
	char* getName();
private:
	int age;
	char *name; 
};


Dog.cpp文件

#include <Dog.h>
#include <iostream>
//c++ 标准库的命名空间
using namespace std;

//Dog::Dog():name("旺财"),age(3){
//	cout << "构造函数 Dog" << this << endl;
//}

//这里构造函数 参数传递进来 进行赋值
Dog::Dog(int age, char *name) :age(age), name(name){
	cout << "带参数的构造函数 Dog" << this << endl;
}

Dog::~Dog()	{
	cout << "析构函数   Dog" << this << endl;
	
}

void Dog::setAge(int age){
	cout << "dog setAge age " << age << endl;
	this ->age = age;

}
int Dog::getAge(){
	return this->age;
}
void Dog::setName(char *name){
	cout << "dog setName name " << name  << endl;
	this->name = name;
}
char* Dog::getName(){
	return this->name;
}

main.cpp文件

#include <Dog.h>
#include <iostream>

using namespace std;


void fun(){

	//Dog dog;//局部变量
	Dog dog = Dog(2, "小黑");


	//dog.setAge(5);
	//dog.setName("jumper");
	cout << "dog age " << dog.getAge() << endl;
	cout << "dog name " << dog.getName() << endl;

}


void setFunValue(Dog &dog){
	dog.setAge(10);
	dog.setName("小白");
	cout << "setFunValue age " << dog.getAge() << endl;
	cout << "setFunValue name " << dog.getName() << endl;

}


//构造函数传参
void main(){

	fun();


	system("pause");

}

使用指针的情况

void fun(){

	//Dog dog;//局部变量
	//Dog dog = Dog(2, "小黑");
	Dog *dog = new Dog(2, "小黑");

	//dog.setAge(5);
	//dog.setName("jumper");
	cout << "dog age " << dog->getAge() << endl;
	cout << "dog name " << dog->getName() << endl;
	delete dog;
	dog = NULL;
}

Dog *dog 代表指针. 访问的时候用 -> 访问.

使用指针和使用对象

没有new 关键字和有new 关键字 的异同.
有new 关键字的是指针 没有new关键字的是对象.

对象: 动态分配内存, 自动回收
指针: 自已申请内存, 需要自己回收

delete dog;
dog = NULL;

如果不自己回收就是野指针, 不会调用析构函数.

结果:

带参数的构造函数 Dog004FF9D8
dog age 2
dog name 小黑
析构函数   Dog004FF9D8
请按任意键继续. . .

例子5 拷贝构造函数 深拷贝浅拷贝

在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。

深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。

简单的来说,浅拷贝是增加了一个指针,指向原来已经存在的内存。而深拷贝是增加了一个指针,并新开辟了一块空间,让指针指向这块新开辟的空间。 浅拷贝在多个对象指向一块空间的时候,释放一个空间会导致其他对象所使用的空间也被释放了,再次释放便会出现错误

看这里
https://blog.csdn.net/qq_27011361/article/details/79518057

猜你喜欢

转载自blog.csdn.net/liudao7994/article/details/81980738