C++ 学习笔记(一)
vscode按F7编译,
vscode运行图:
类,构造函数,拷贝函数
#include <iostream>
using nam``espace std;
class CTime
{
private:
int hour,minute,second;
public:
void print()
{
cout<<hour<<":"<<minute<<":"<<second<<endl;
}
CTime(int h,int m,int s) //带参数的构造函数
{
hour=h;
minute=m;
second=s;
}
CTime(CTime &t) //拷贝构造函数,参数为同类对象的引用
{
hour=t.hour;
minute=t.minute;
second=t.second;
}
};
int main()
{
CTime t1(8,30,20); //创建对象时以参数的形式为对象初始化
t1.print();
CTime t2(t1);
t2.print();
return 0;
}
常对象和常对象函数
#include <iostream>
using namespace std;
class Point
{
int x,y;
public:
Point(int a,int b) //构造函数
{
x=a;
y=b;
}
void MovePoint(int a,int b) //一般成员
{
x+=a;
y+=b;
}
void print()const //常成员函数
{
cout<<"x="<<x<<" y="<<y<<endl;
}
};
int main()
{
Point point1(1,1); //Point1为普通对象
point1.print();
const Point point2(2,2); //point2为常对象
point1.MovePoint(3,3); //普通成员函数调用一般成员对象,常成员函数不能更新对象数据,
point2.print(); //也不能调用其他非常的成员函数,但可以被其他成员函数调用
point1.print();
return 0;
}
对象的动态建立和释放
~A为析构函数,常用于释放内存单元。
类体外定义函数时,函数名前要加类名和作用域运算符::。
#include <iostream>
#include <string>
using namespace std;
class A
{
private:
string name;
public:
A();
A(string); //定义函数
~A(); //析构函数,与构造函数类似,只在函数名前加~,不带任何参数,也不带返回值(包括void类型),常用于释放内存单元
};
A::A //在类体外定义成员函数时,函数名前要加类名和作用域运算符::
{
cout<<"默认构造函数正在执行,创建无名对象"<<endl;
}
A::A(string s):name(s)
{
cout<<"带参构造函数A()正在执行,创建对象:"<<name<<endl;
}
A::~A()
{
cout<<"~A()正在执行,析勾对象:"<<name<<endl;
}
int main()
{
A *pt1 =new A("aaa"); //调用带参数的构造函数,创建对象aaa
A *pt2 =new A(); //调用默认构造函数,创建无名对象
delete pt2; //delete调用析构函数撤销无名对象
A *ptr =&A(); //调用默认构造函数创建无名对象
//该无名对象的撤销是系统自动调用析构函数进行的
delete pt1; //delete调用析构函数撤销对象aaa
return 0;
}
运行结果应为:
带参构造函数A()正在执行,创建对象:aaa
默认构造函数正在执行,创建无名对象
~A()正在执行,析构对象
默认构造函数正在执行,创建无名对象
~A()正在执行,析构对象
~A()正在执行,析构对象aaa
但是一直报错运行不出来,可能vscode不能识别::符号,现将函数的定义移至类内,程序如下:
#include <iostream>
#include <string>
using namespace std;
class A
{
private:
string name;
public:
A()
{
cout<<"默认构造函数正在执行,创建无名对象"<<endl;
}
A(string s):name(s) //定义函数
{
cout<<"带参构造函数A()正在执行,创建对象:"<<name<<endl;
}
~A() //析构函数,与构造函数类似,只在函数名前加~,不带任何参数,也不带返回值(包括void类型),常用于释放内存单元
{
cout<<"~A()正在执行,析勾对象:"<<name<<endl;
}
};
//A::A() //在类体外定义成员函数时,函数名前要加类名和作用域运算符::
//{
// cout<<"默认构造函数正在执行,创建无名对象"<<endl;
//}
//A::A (string s):name(s)
///{
//cout<<"带参构造函数A()正在执行,创建对象:"<<name<<endl;
//}
//A::~A()
//{
//cout<<"~A()正在执行,析勾对象:"<<name<<endl;
//}
int main()
{
A *pt1 =new A("aaa"); //调用带参数的构造函数,创建对象aaa
A *pt2 =new A(); //调用默认构造函数,创建无名对象
delete pt2; //delete调用析构函数撤销无名对象
// A *ptr =&A(); //调用默认构造函数创建无名对象
//该无名对象的撤销是系统自动调用析构函数进行的
delete pt1; //delete调用析构函数撤销对象aaa
return 0;
}
运行结果:
带参构造函数A()正在执行,创建对象:aaa
默认构造函数正在执行,创建无名对象
~A()正在执行,析勾对象:
~A()正在执行,析勾对象:aaa
this指针
#include <iostream>
using namespace std;
class Point
{
private: //Point类的两个私有数据成员
int x,y;
public: //构造函数,初始化数据成员
Point(int a,int b)
{
x=a;
y=b;
}
void MovePoint(int a,int b) //成员函数,计算移动后的新坐标
{
this->x+=a; //this指针指向对象,this->x表示对象的数据成员,
this->y+=b; //等价于x+=a
}
void print() //成员函数,输出点的坐标
{
cout<<"x="<<x<<", y="<<y<<endl;
}
};
int main()
{
Point point1(10,10); //创建对象point1并初始化
point1. MovePoint(2,2); //通过对象point1调用成员函数MovePoint()
point1.print(); //通过对象point1调用成员函数print()
return(0);
}
运行结果:
x=12, y=12
友元函数和友元类
有时需要定义一些函数,这些函数不是类的一部分,但又要频繁访问类的数据成员,这时将这些函数定义为该类的友元函数。
友元函数
友元函数是类外的函数,但声明要放在类内的私有段或公有段
#include <iostream>
using namespace std;
class A
{
private:
int x;
friend int func(A &a,int j); //声明友元函数func(),友元函数是类外的函数,但声明要放在类内的私有段或公有段
public:
A(int i) //构造函数
{
x=i;
}
};
int func(A &a,int j)
{
return a.x+j; //在func()中通过类A的对象a调用了类A的私有成员x
}
int main()
{
A a(3);
cout<<func(a,6); //友元函数不属于类,直接调用,不要用a.func()
return 0;
}
运行结果:9
友元成员函数
要在public段声明,在类外定义
#include <iostream>
using namespace std;
class B;
class A
{
private:
int x;
public:
A()
{
this->x=0; //等价x=0
}
void display(B &v); //成员函数声明
};
class B
{
private:
int y;
int z;
public:
B() //类B的构造函数声明,无参数
{
this->y=0; //类B的私有成员y,z初始化为0
this->z=0;
}
B(int y,int z) //类B的构造函数声明,含两个参数
{
this->y=y; //类B的私有成员y,z初始化为为参数值
this->z=z;
}
friend void A::display(B &); //类A 的成员函数display()被声明为类B友元函数
};
void A::display(B &v) //友元函数display()定义
{
cout<<"v.y="<<v.y<<endl;
cout<<"v.z="<<v.z<<endl; //友元函数内可以通过类B的对象访问B的私有成员y,z
x=v.y+v.z; //x等价于this->x
cout<<"x="<<x<<endl;
}
int main()
{
A a;
B b(2,3);
a.display(b);
return 0;
}
运行结果:
v.y=2
v.z=3
x=5
友元类
#include <iostream>
using namespace std;
class B;
class A
{
private:
int x;
public:
friend class B; //声明类B是类A的友元类
void display() //成员函数声明
{
cout<<x<<endl;
}
};
class B
{
private:
A a;
public:
B(int i) //类B的构造函数声明,无参数
{
a.x=i;
}
void display() //成员函数声明
{
cout<<"a.x="<<a.x<<endl; //类B的成员函数可以直接访问类A的私有成员x
}
void display1() //成员函数声明
{
cout<<"a.display()=";
a.display(); //类B的成员函数可以直接访问类A的私有成员x
}
};
int main()
{
B b(10);
b.display();
b.display1();
}
运行结果:
a.x=10
a.display()=10
类的静态成员和静态成员函数
静态数据成员
数据类型前加关键字static。
当同一类定义了多个对象时,不同对象的静态数据成员实际上是同一变量。可实现数据在各个对象间的共享和消息传递,它的值可以更新。
静态数据成员属于类,它的初始化与一般数据成员初始化不一样,不是通过构造函数进行。要在类体外初始化,但要在类内进行声明。
#include <iostream>
using namespace std;
class Myclass
{
public:
Myclass(int i,int j,int k) //构造函数定义
{
a=i;
b=j;
c=k;
Sum+=i+j+k;
}
void GetSum() //成员函数GetSum() 定义,用于输出Sum的值
{
cout<<"Sum="<<Sum<<endl;
}
private:
int a,b,c;
static int Sum; //声明类的的静态数据成员Sum
};
int Myclass::Sum=0; //定义并初始化静态数据成员
int main()
{
Myclass M(1,2,3);
M.GetSum();
Myclass N(4,5,6);
N.GetSum(); //输出静态数据成员Sum的值
M.GetSum(); //输出静态数据成员Sum的值
}
运行结果:
Sum=6
Sum=21
Sum=21
静态成员函数
函数类型前加关键字static。
静态成员函数属于类而不是具体某个对象。
静态成员函数不能直接访问类的非静态数据成员,也无法直接访问非静态成员函数,只能直接访问静态成员函数和静态数据成员。但它可以通过类的对象间接访问非静态数据成员和非静态成员函数。
如果在类体内只是静态成员函数的声明,在类体外进行函数定义时不能再指定关键字static。
#include <iostream>
#include <string>
using namespace std;
class Student
{
static int number; //声明类的的静态数据成员
string name;
public:
void set(string str) //构造函数定义
{
name=str;
number++; //非静态成员函数调用静态数据成员
}
void print() //非静态成员函数print()调用静态数据成员
{
cout<<"1:The number of the studens is" <<number<<"numbers."<<endl;
}
static void print2(Student &s) //静态成员函数print2()
{
cout<<"2:The number of the studens is" <<number<<"numbers."<<endl;
cout<<s.name<<endl; //通过对象s调用非静态数据成员
s.print(); //通过对象s调用非静态成员函数
}
};
int Student::number=0; //初始化静态数据成员只能在类外,并且数据类型前不加static
int main()
{
Student s;
s.set("smith");
s.print2(s);
return(0);
}
运行结果:
2:The number of the studens is1numbers.
smith
1:The number of the studens is1numbers.