目录
一、main.cpp
1.如何创建一个类
类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个变量;创建对象的过程也叫类的实例化。每个对象都是类的一个具体实例(Instance),拥有类的成员变量和成员函数。
与结构体一样,类只是一种复杂数据类型的声明,不占用内存空间。而对象是类这种数据类型的一个变量,或者说是通过类这种数据类型创建出来的一份实实在在的数据,所以占用内存空间。
1类的定义
类是用户自定义的类型,如果程序中要用到类,必须提前说明,或者使用已存在的类(别人写好的类、标准库中的类等),C++语法本身并不提供现成的类的名称、结构和内容。
#include <iostream>
using namespace std;
class Student
{
public:
const char* strName;
int Age;
float Score;
public:
void Show()
{
cout << strName << " " << Age << " " << Score << endl;
}
};
int main()
{
Student stu;
stu.strName = "小明";
stu.Age = 18;
stu.Score = 99.9;
stu.Show();
Student stu1;
stu1.strName = "小红";
stu1.Age = 18;
stu1.Score = 100.0;
stu1.Show();
Student* p = new Student;
p->strName = "小迪";
p->Age = 18;
p->Score = 100.0;
p->Show();
system("pause");
return 0;
}
输出:
小明 18 99.9
小红 18 100
小迪 18 100
请按任意键继续. . .
2.输入输出
cin和cout是c++中的标准输入输出流。
1 cin
cin的一般用法:
cin>>变量a>>变量b>>变量c
cin会自动辨别变量的类型,如a可以是char,b可以是int,c可以是float。
接收字符串时,遇到空格,tab键和换行符都会结束接收。
2 cout
cout的一般用法:
cout<<表达式1<<表达式2<<表达式3;
如要换行可使用cout<<endl;语句。
和cin一样,cout会自动检测表达式类型输出。
#include <iostream>
using namespace std;
int main()
{
int a = 10;
char b = 'x';
cout << "Hello C++" << endl;
cout << a <<" "<< b << endl;
cin >> a;
cout << a << endl;
system("pause");
return 0;
}
输出:
Hello C++
10 x
3.命名空间
C++标准中引入命名空间的概念,是为了解决不同模块或者函数库中相同标识符冲突的问题。有了命名空间的概念,标识符就被限制在特定的范围(函数)内,不会引起命名冲突。最典型的例子就是std命名空间,C++标准库中所有标识符都包含在该命名空间中。
如果确信在程序中引用某个或者某些程序库不会引起命名冲突(即库中的标识符不会在程序中代表其他函数名称),那么可以通过using操作符来简化对程序库中标识符(通常时函数)的使用,例如:using namespace std;那么就可以不用在标识符在前缀std::来使用C++标准库库中的函数了。
<iostream>和<iostream.h>是不一样,前者没有后缀,实际上,在你的编译器include文件夹里面可以看到,二者是两个文件,打开文件就会发现,里面的代码是不一样的。后缀为.h的头文件c++标准已经明确提出不支持了,早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,c++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。因此,当使用<iostream.h>时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的c++实现;当使用<iostream>的时候,该头文件没有定义全局命名空间,必须使用 namespacestd;这样才能正确使用cout。
#include <iostream>
using namespace std;
int a = 10;
namespace Person
{
const char* name = "小明";
int age = 18;
}
namespace Animal
{
const char* name = "小花";
int age = 2;
}
int main()
{
//std::cout << "Hello" << std::endl;
/*int a = 100;
cout << a << endl;
cout << ::a << endl;*/
using namespace Person;
cout << name <<" " << age << endl;
system("pause");
return 0;
}
输出:
小明 18
请按任意键继续. . .
D:\c++\类和对象\x64\Debug\类和对象.exe (进程 24152)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
4.动态分配内存空间
1 new
1.开辟单变量地址空间
使用new运算符时必须已知数据类型,new运算符会向系统堆区申请足够的存储空间,如果申请成功,就返回该内存块的首地址,如果申请不成功,则返回零值。
new运算符返回的是一个指向所分配类型变量(对象)的指针。对所创建的变量或对象,都是通过该指针来间接操作的,而动态创建的对象本身没有标识符名。
一般使用格式:
格式1:指针变量名=new类型标识符;
格式2:指针变量名=new类型标识符(初始值);
格式3:指针变量名=new类型标识符[内存单元个数]
说明:格式1和格式2都是申请分配某一数据类型所占字节数的内存空间;但是格式2在内存分配成功后,同时将一初值存放到该内存单元中;而格式3可同时分配若千个内存单元,相当于形成一个动态数组。例如:
new int; //开辟一个存放整数的存储空间,返回一个指向该存储空间的地址。
int *p1 = new int //即为将一个int类型的地址赋值给整型指针
p int *p2 = new int(5) //作用同上,但是同时将整数空间赋值为5
2 delete
1. 删除单变量地址空间
int *p = new int;
delete p; //释放单个int的空间
2.删除数组空间
int *p = new int[5];
I
delete[]p; //释放int数组空间
3 注意事项
1.new和delete都是内建的操作符,语言本身所固定了,无法重新定制,想要定制new和
delete的行为,徒劳无功的行为。
2.动态分配失败,则返回一个空指针(NULL),表示发生了异常,堆资源不足,分配失败。
3.指针删除与堆空间释放。删除一个指针p(deletep;)实际意思是删除了p所指的目标(变
量或对象等),释放了它所占的堆空间,而不是删除p本身(指针p本身并没有撤销,它自己仍然存在,该指针所占内存空间并未释放),释放堆空间后,p成了野指针。
4.内存泄漏(memory leak)和重复释放。new与delete是配对使用的,delete只能释放堆空
间。如果new返回的指针值丢失,则所分配的堆空间无法回收,称内存泄漏,所以必须妥善保存new返回的指针,以保证不发生内存泄漏,也必须保证不会重复释放堆内存空间。
5.动态分配的变量或对象的生命期。我们也称堆空间为自由空间(free store),但必须记住
释放该对象所占堆空间,并只能释放一次,在函数内建立,而在函数外释放,往往会出错。
6.要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问。
#include <iostream>
using namespace std;
int main()
{
char* p1 = new char;
*p1 = 100;
cout << *p1 << endl;
int* p2 = new int(4);
cout << *p2 << endl;
delete p2;
system("pause");
return 0;
}
输出:
d
4
请按任意键继续. . .
5.默认参数
C++中允许为函数提供默认参数,又名缺省参数。
注意函数声明时,必须按照从右向左的顺序,依次给与默认
函数的默认参数要在函数声明的时候给出。
#include <iostream>
using namespace std;
void Show(int a, char b, float c);
int main()
{
cout << "--------------" << endl;
Show(200,'b',2.16);
cout << "--------------" << endl;
system("pause");
return 0;
}
void Show(int a = 100, char b = 'a', float c = 3.14)
{
cout << a << endl;
cout << b << endl;
cout << c << endl;
}
输出:
--------------
200
b
2.16
--------------
请按任意键继续. . .
6.函数重载
函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。
承数的重载使得C++程序员对完成类似功能的不同函数可以统一命名,减少了命名所花的心
思。例如,可能会需要一个求两个整数的最大值的函数,也可能还要写一个求三个实数的最大值的函数,这两个函数的功能都是求最大值,那么就都命名为 Max即可。
在调用同名函数时,编译器怎么知道到底调用的是哪个函数呢?编译器是根据函数调用语句中实参的个数和类型来判断应该调用哪个函数的。因为重载函数的参数表不同,而调用函数的语句给出的实参必须和参数表中的形参个数和类型都匹配,因此编译器才能够判断出到底应该调用哪个函数。
#include <iostream>
using namespace std;
double Area(double x, double y)
{
return x * y;
}
int Area(int x, int y)
{
return x * y;
}
double Area(double r)
{
return 3.14 * r * r;
}
//函数重载 函数名相同 参数链表不同
//与函数的返回值无关
//尽量不使用默认参数
int main()
{
cout << Area(2, 3) << endl;
cout << Area(2) << endl;
return 0;
}
输出:
6
12.56
D:\c++\类和对象\x64\Debug\类和对象.exe (进程 12268)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
7.引用
1.在引用的使用中,单纯给某个变量去别名是毫无意义的,引用的目的主要用于在函数参数
的传递中,解决大块数据或对象的传递效率和空间不如意的问题
2.用引用传递函数的参数,能保证参数在传递的过程中不产生副本,从而提高传递效率,同
时通过const的使用,还可以保证参数在传递过程中的安全性
3.引用本身是目标变量或对象的别名,对引用的操作本质上就是对目标变量或对象的操作。
因此能使用引用时尽量使用引用而非指针
4、指针与引用的区别,指针可以装地址,可以偏移,可以间接引用。引用只能实现指针间接
引用的功能,如果是new的空间必须要用引用。
#include <iostream>
using namespace std;
int main()
{
int a = 100;
int& ra = a;
int* p = &a;
int*& rp = p;
cout << ra << endl;
ra = 200;
cout << a << endl;
*rp = 500;
cout << *rp << endl;
system("pause");
return 0;
}
输出:
100
200
500
请按任意键继续. . .
8.初始化列表
#include <iostream>
using namespace std;
class Student
{
public:
char* m_Name;
int m_Age;
public:
Student(const char* name, int age);
};
Student::Student(const char* name, int age) :m_Name(), m_Age(age)
{
}
class AA
{
public:
int m_a;
int m_b;
public:
AA(int n);
};
AA::AA(int n):m_b(n),m_a(m_b)
{
}
int main()
{
/*Student stu("张三", 13);
cout << stu.m_Name << " " << stu.m_Age << endl;*/
AA a(10);
cout << a.m_a << " " << a.m_b << endl;
system("pause");
return 0;
}
#include <iostream>
using namespace std;
class AA
{
public:
const int a;
int b;
public:
AA():a(10),b(10)
{
}
AA(int n):a(n),b(20)
{
}
};
int main()
{
AA a;
cout << a.a << " " << a.b << endl;
AA b(30);
cout << b.a << " " << b.b << endl;
system("pause");
return 0;
}
输出:
10 10
30 20
请按任意键继续. . .
9.访问修饰符
//#include <iostream>
//using namespace std;
//
//class Student
//{
//private:
// const char* name;
//
// int age;
//
// int score;
//public:
// void show();
//};
//void Student :: show()
//{
// cout<< name << " " << age << " " << score << endl;
//}
//int main()
//{
// Student stu;
// stu.show();
//
// system("pause");
// return 0;
//}
#include <iostream>
using namespace std;
class Student
{
public:
const char* strName;
private:
int Age;
protected:
float Score;
public:
void Show();
};
void Student:: Show()
{
cout << strName << endl;
cout << Age << endl;
cout << Score << endl;
}
int main()
{
Student stu;
stu.strName = "小红";
stu.Show();
system("pause");
return 0;
}
输出:
小红
-858993460
-1.07374e+08
请按任意键继续. . .
二、接口函数
#include <iostream>
using namespace std;
class Student
{
private:
const char* Name;
int Age;
int Score;
public:
void SetName(const char* str);
void SetAge(int n);
void SetScore(int n);
const char* GetName();
int GetAge();
int GetScore();
};
void Student:: SetName(const char* str)
{
Name = str;
}
void Student::SetAge(int n)
{
Age = n;
}
void Student::SetScore(int n)
{
Score = n;
}
const char* Student:: GetName()
{
return Name;
}
int Student::GetAge()
{
return Age;
}
int Student::GetScore()
{
return Score;
}
int main()
{
Student stu;
stu.SetName("张三");
stu.SetAge(18);
stu.SetScore(100);
cout << stu.GetName() << " " << stu.GetAge() << " " << stu.GetScore() << endl;
system("pause");
return 0;
}
输出:
张三 18 100
请按任意键继续. . .
三、链表类
#include <iostream>
using namespace std;
class List
{
struct Node
{
int value;
Node* pNext;
};
private:
Node* pHead = NULL;
Node* pEnd = NULL;
int n;
public:
void PushBack(int n);
void Print();
};
void List::PushBack(int n)
{
Node* pTemp = new Node;
pTemp->value = n;
pTemp->pNext = NULL;
if (pHead == NULL)
{
pHead = pTemp;
}
else
{
(pEnd)->pNext = pTemp;
}
pEnd = pTemp;
n++;
}
void List::Print()
{
Node* pMark = pHead;
while (pMark != NULL)
{
cout << pMark->value << endl;
pMark = pMark->pNext;
}
}
int main()
{
List list;
list.PushBack(1);
list.PushBack(2);
list.PushBack(3);
list.PushBack(4);
list.Print();
return 0;
}
输出:
1
2
3
4
D:\c++\类和对象\x64\Debug\类和对象.exe (进程 24912)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
四、设计一个立方体类
#include <iostream>
using namespace std;
class Cube
{
private:
int m_L;
int m_W;
int m_H;
public:
void SetLong(int l);
int GetLong();
void SetWeight(int w);
int GetWeight();
void SetHight(int h);
int GetHight();
public:
int calculateS();
int calculateV();
public:
bool IsSameByClass(Cube& c2);
};
void Cube::SetLong(int l)
{
m_L = l;
}
int Cube::GetLong()
{
return m_L;
}
void Cube::SetWeight(int w)
{
m_W = w;
}
int Cube::GetWeight()
{
return m_W;
}
void Cube::SetHight(int h)
{
m_H = h;
}
int Cube::GetHight()
{
return m_H;
}
int Cube::calculateS()
{
return 2 * (m_L * m_H + m_L * m_W + m_H * m_W);
}
int Cube::calculateV()
{
return m_L * m_W * m_H;
}
bool IsSame(Cube &c1,Cube &c2)
{
if (c1.GetLong() == c2.GetLong() && c1.GetWeight() == c2.GetWeight() && c1.GetHight() == c2.GetHight())
{
return true;
}
else
{
return false;
}
}
bool Cube::IsSameByClass(Cube& c2)
{
if (m_L == c2.GetLong() && m_W == c2.GetWeight() && m_H == c2.GetHight())
{
return true;
}
else
{
return false;
}
}
int main()
{
Cube c1;
c1.SetLong(10);
c1.SetWeight(10);
c1.SetHight(10);
cout << "c1的面积为:" << c1.calculateS() << endl;
cout << "c1的体积为:" << c1.calculateV() << endl;
Cube c2;
c2.SetLong(10);
c2.SetWeight(10);
c2.SetHight(10);
bool ret = c1.IsSameByClass(c2);
if (ret)
{
cout << "c1和c2是相等的" << endl;
}
else
{
cout << "不相等" << endl;
}
system("pause");
return 0;
}
输出:
c1的面积为:600
c1的体积为:1000
c1和c2是相等的
请按任意键继续. . .
五、点和圆的位置关系
1.main.cpp
#include <iostream>
using namespace std;
#include "circle.h"
#include "point.h"
//class Point
//{
//private:
// int m_X;
// int m_Y;
//public:
// void SetX(int x);
// int GetX();
// void SetY(int y);
// int GetY();
//};
//class Circle
//{
//private:
// int m_R;
// Point m_Center;
//public:
// void SetR(int r);
// int GetR();
// void SetCenter(Point center);
// Point GetCenter();
//};
//void Circle::SetR(int r)
//{
// m_R = r;
//}
//int Circle::GetR()
//{
// return m_R;
//}
//void Point::SetX(int x)
//{
// m_X = x;
//}
//int Point::GetX()
//{
// return m_X;
//}
//void Point::SetY(int y)
//{
// m_Y = y;
//}
//int Point::GetY()
//{
// return m_Y;
//}
//void Circle::SetCenter(Point center)
//{
// m_Center = center;
//}
//Point Circle::GetCenter()
//{
// return m_Center;
//}
void IsInCircle(Circle& c, Point& p)
{
int distance =
(c.GetCenter().GetX() - p.GetX()) * (c.GetCenter().GetX() - p.GetX()) +
(c.GetCenter().GetY() - p.GetY()) * (c.GetCenter().GetY() - p.GetY());
int rdistance = c.GetR() * c.GetR();
if (distance > rdistance)
{
cout << "点在圆外" << endl;
}
else if (distance == rdistance)
{
cout << "点在圆上" << endl;
}
else
{
cout << "点在圆内" << endl;
}
}
int main()
{
Circle c;
c.SetR(10);
Point center;
center.SetX(10);
center.SetY(0);
c.SetCenter(center);
Point p;
p.SetX(10);
p.SetY(9);
IsInCircle(c, p);
system("pause");
return 0;
}
2.Circle.h
#include "Point.h"
class Circle
{
private:
int m_R;
Point m_Center;
public:
void SetR(int r);
int GetR();
void SetCenter(Point center);
Point GetCenter();
};
3.Circle.cpp
#include "Circle.h"
void Circle::SetR(int r)
{
m_R = r;
}
int Circle::GetR()
{
return m_R;
}
void Circle::SetCenter(Point center)
{
m_Center = center;
}
Point Circle::GetCenter()
{
return m_Center;
}
4.Point.h
#pragma once
#include <iostream>
using namespace std;
class Point
{
private:
int m_X;
int m_Y;
public:
void SetX(int x);
int GetX();
void SetY(int y);
int GetY();
};
5.Point.cpp
#include "Point.h"
void Point::SetX(int x)
{
m_X = x;
}
int Point::GetX()
{
return m_X;
}
void Point::SetY(int y)
{
m_Y = y;
}
int Point::GetY()
{
return m_Y;
}
输出:
点在圆内
请按任意键继续. . .