用结构体数据的安全性得不到保证。

使用类对数据进行封装,只能通过函数修改类中的数据

(1)类的定义

class 类名
{
private:
protected:
public:
};

private:定义私有成员,只能被类本身的成员函数和友元访问。派生类和其他类均不能访问。若数据没有指明类型,默认为私有。

public:定义公有成员,可被程序中任何代码访问。

protected:定义保护成员,能被本身成员函数,友元,派生类访问。

(2)成员函数的定义

a、在类中定义

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; class Student
{
private:
string Name;
float Phi,Math,Ave;
public:
void set(string name,float phi,float math)
{
Name=name;
Phi=phi;
Math=math;
}
void Average()
{
Ave=(Phi+Math)/;
}
void Display()
{
cout<<Name<<" "<<Phi<<" "<<Math<<" "<<Ave;
}
}; int main()
{
Student stud;
stud.set("zhangsan",,);
stud.Average();
stud.Display();
return ;
}

b、在类外定义

(考虑到有些函数复杂,在类内写不好看)

先在类内声明,然后在类外定义的形式是

函数返回值类型 类名 ::函数名称()

{}

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; class Date
{
private :
int year,month,day;
public:
void setDate(int,int,int);
bool IsLeap();
void print()
{
cout<<year<<" "<<month<<" "<<day<<endl;
}
}; void Date::setDate(int n,int y,int r)
{
year=n;month=y;day=r;
} bool Date::IsLeap()
{
if(year%==||year%==&&year%) return true;
return false;
} int main()
{
Date dt;
dt.setDate(,,);
if(dt.IsLeap()) cout<<"yes\n";
else cout<<"no\n";
dt.print();
return ;
}

(3)成员的访问

a、对于数据成员的访问

对象名.成员名   对象指针名->成员名  (*对象指针名).成员名

b、对于成员函数的访问

对象名.成员函数名(参数表)  对象指针名->成员函数名(参数表) (*对象指针名).成员函数名(参数表)

#include<iostream>
#include<cstdio>
using namespace std; class Student
{
private :
string name;
float Math,Phi,Ave;
public:
void setDate(string nam,float math,float phi)
{
name=nam;
Math=math;
Phi=phi;
}
void Average()
{
Ave=(Math+Phi)/;
}
void print()
{
cout<<name<<" "<<Math<<" "<<Phi<<" "<<Ave<<endl;
}
}; int main()
{
Student stu,*stud;
stud=&stu;
//一开始我没定义 stu,直接定义个指针用了,这样不行。
stud->setDate("zhangsan",,);
stud->Average();
stud->print();
return ;
}
#include<iostream>
#include<cstdio>
using namespace std; class Student
{
private:
string Name;
int Phi,Math;
public:
void setDate();
void print()
{
cout<<Name<<" "<<Phi<<" "<<Math<<endl;
}
}; void Student::setDate()//在类作用域内,直接使用即可访问
{
cin>>Name>>Phi>>Math;
} int main()
{
Student stud;
stud.setDate();
stud.print();
return ;
}

(4)构造函数

构造函数就是对类内的数据初始化,定义一个类的对象时自动调用,如果不写构造函数,就调用系统默认的构造函数。

性质:与类名相同 无返回值 可以重载

#include<iostream>
#include<cstdio>
using namespace std; class Cuboid //长方体类
{
private:
int length,width,height;
public:
Cuboid();//无参构造函数
Cuboid(int,int,int);//有参构造函数
int volume();//计算体积
}; Cuboid::Cuboid()
{
length=width=height=;
} Cuboid::Cuboid(int l,int w,int h)
{
length=l;
width=w;
height=h;
} int Cuboid::volume()
{
return length*width*height;
} int main()
{
Cuboid cuboid1;
cout<<"cuboid1的体积为:"<<cuboid1.volume()<<endl;
Cuboid cuboid2(,,);
cout<<"cuboid2的体积为:"<<cuboid2.volume()<<endl;
return ;
}

#include<iostream>
#include<cstdio>
using namespace std; class Cuboid
{
private:
int h,w,l;
public:
/* Cuboid(int hh=10,int ww=20,int ll=30)另一种写法
{
h=hh;w=ww;l=ll;
}*/
Cuboid(int hh=,int ww=,int ll=);//声明时有默认参数
int volume()
{
return h*w*l;
}
}; Cuboid::Cuboid(int hh,int ww,int ll)//不用再写默认参数
{
h=hh;
w=ww;
l=ll;
} int main()
{
Cuboid cuboid1;
cout<<cuboid1.volume()<<endl;
Cuboid cuboid2();
cout<<cuboid2.volume()<<endl;
Cuboid cuboid3(,);
cout<<cuboid3.volume()<<endl;
return ;
}

也可以这样初始化

Cuboid(int h,int w,int len):height(h),width(w),length(len){}

(5)拷贝构造函数

拷贝构造函数的名称与类名一致,函数的形式参数是本类型的一个引用变量。

Sample (Sample &S);

对象1=对象2 //对象1和对象2必须是同一个类

将一个对象的非静态数据成员的值一一赋值给另一对象的对应成员。

Sample S2(S1);

Sample S2=S1;两者等价

a、

#include<iostream>
#include<cstdio>
using namespace std; class Sample
{
private:
int data;
public:
Sample(int dt)
{
data=dt;
}
void print()
{
cout<<data<<endl;
}
}; int main()
{
Sample s1();
Sample s2=s1;
s2.print();
}

b、自定义拷贝构造函数 并不是一一赋值

#include<iostream>
#include<cstdio>
using namespace std; class Sample
{
private:
int a,b,c,d;
public:
Sample(int aa,int bb,int cc,int dd)
{
a=aa;b=bb;c=cc;d=dd;
}
Sample(Sample &S)
{
a=S.a;b=S.b;c=S.c; d=S.d+;
}
void print()
{
cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
}
}; int main()
{
Sample dt1(,,,);
Sample dt2=dt1;
//Sample dt2(dt1);
dt2.print();
return ;
}

(6)析构函数

作用在对象脱离作用域时释放相关资源,清理善后工作。

析构函数名和类名相同只是在函数名前面加~符号

无参数 无返回值 只能有一个析构函数 不写虚构函数调用系统自己的

#include<iostream>
#include<cstdio>
using namespace std; class Cstudent
{
private:
int num;
string name;
public:
Cstudent(string nam,int nnum)
{
name=nam;
num=nnum;
cout<<name<<" Constructor called.\n";
}
void display()
{
cout<<"学号:"<<num<<endl;
cout<<"姓名:"<<name<<endl;
}
~Cstudent()
{
cout<<name<<" Destructor called\n";
}
}; int main()
{
Cstudent stud1("zhangsan",);
Cstudent stud2("lisi",);
return ;
}

一般情况下,调用析构函数的次序与调用构造函数的次序相反。

(7)静态成员--静态数据成员

静态数据成员被类内所有的对象共享,某个对象对静态数据成员做出修改,则其他所有对象也共享被修改后的值。

静态数据成员的存储空间不会随着对象的产生而分配,也不会随着对象的消失而释放。

因此,静态数据成员不能在类体内初始化。

如果未对静态数据成员赋初值,默认为0;其他成员不会默认为0;

class Cstudent
{
private:
string name;
int score;
static int studenttotal;
static int sumscore;
public:
Cstudent(string nam,int scor)
{
name=nam;
score=scor;
studenttotal++;
sumscore+=scor;
cout<<name<<" Constructor called.\n";
}
static float average();
~Cstudent();
}; int Cstudent::studenttotal=; int Cstudent::sumscore=;

(8)静态成员--静态成员函数

一般情况下,静态成员函数只访问静态成员。也可以访问非静态成员,但要指明其所属对象,但这样麻烦,所以不用。

class Cstudent
{
private:
string name;
int score;
static int studenttotal;
static int sumscore;
public:
Cstudent(string nam,int scor)
{
name=nam;
score=scor;
studenttotal++;
sumscore+=scor;
cout<<name<<" Constructor called.\n";
}
static float average();//*******
~Cstudent();
}; int Cstudent::studenttotal=; int Cstudent::sumscore=; float Cstudent::average() //**********
{
return (sumscore*./studenttotal);
}

静态成员的访问

一般是:类名::静态数据成员名

#include<iostream>
#include<cstdio>
using namespace std; class Cstudent
{
private:
string name;
int score;
static int studenttotal;
static int sumscore;
public:
Cstudent(string nam,int scor)
{
name=nam;
score=scor;
studenttotal++;
sumscore+=scor;
cout<<name<<" Constructor called.\n";
}
static float average();//*******
~Cstudent();
}; int Cstudent::studenttotal=; int Cstudent::sumscore=; float Cstudent::average() //**********
{
return (sumscore*./studenttotal);
} Cstudent::~Cstudent()
{
studenttotal--;
sumscore-=score;
cout<<name<<" Destructor called.\n";
} int main()
{
Cstudent stud[]={Cstudent("zhangsan",),Cstudent("wangwu",)};
cout<<Cstudent::average()<<endl;
return ;
}

(9)对象的存储

只有数据成员占有的内存空间的大小,而没有包括成员函数。

//类的空间
#include<iostream>
#include<cstdio>
using namespace std; class Data
{
private:
int a,b;
public:
void setdata(int aa,int bb)
{
a=aa;
b=bb;
}
void print()
{
cout<<a<<" "<<b<<endl;
} }; int main()
{
Data x,y;
cout<<sizeof(int)<<endl;
cout<<sizeof(x)<<endl;
return ;
}

()

(10)this指针

this指针指向正在操作该成员函数的对象。

this指针最常用的两种情况:

①该函数的返回的是对调用该函数的对象的引用 即return *this

②当参数与成员变量名相同时,由于参数优先,所以对数据成员必须显式使用this指针修饰。

//this指针
#include<iostream>
#include<cstdio>
using namespace std; class Point
{
private:
int x,y;
public:
Point(int xx,int yy)
{
x=xx;y=yy;
}
Point& setPoint(int x,int y)
{
this->x=x+;
(*this).y=y+;
return *this;
}
int getX(){return x;}
int getY(){return y;}
}; int main()
{
Point p1(,);
cout<<"执行setPoint()前p1:"<<p1.getX()<<","<<p1.getY()<<endl;
//cout<<p1.setPoint(8,8);这行是错的
p1.setPoint(,);
//p1=p1.setPoint(8,8);和上一行等价
cout<<"执行setPoint()后p1:"<<p1.getX()<<","<<p1.getY()<<endl;
return ;

(11)常对象

常对象是指对象的数据成员的值不能被改变,常对象必须在定义的同时进行初始化。

且一旦定义就不能再改变。常对象只能调用const成员函数。普通对象可以调用const成员函数。

//常对象
#include<iostream>
#include<cstdio>
using namespace std; class Rectangle
{
private:
int width;
int length;
public:
Rectangle()
{
width=;
length=;
}
Rectangle(int w,int len)
{
width=w;length=len;
}
int area() const
{
return width*length;
}
}; int main()
{
Rectangle r1(,);
const Rectangle r2(,);
//Rectangle const r2(6,8);等价
cout<<"r1的面积:"<<r1.area()<<endl;
cout<<"r2的面积:"<<r2.area()<<endl;
return ;
}

常对象中的某个数据成员想要修改,则声明为mutable

//常对象
#include<iostream>
#include<cstdio>
using namespace std; class Rectangle
{
private:
int width;
mutable int length;
public:
Rectangle()
{
width=;
length=;
}
Rectangle(int w,int len)
{
width=w;length=len;
}
int area() const
{
length*=;
return width*length;
}
}; int main()
{
Rectangle r1(,);
const Rectangle r2(,);
//Rectangle const r2(6,8);等价
cout<<"r1的面积:"<<r1.area()<<endl;
cout<<"r2的面积:"<<r2.area()<<endl;
return ;
}

指向常对象的指针变量

const 类名 *指针变量名

const Rectangle *ptr=&r1;

不能通过ptr修改r1,但ptr也可以指向别的。

(12)常数据成员

将数据成员声明为const型。不能被赋值,类体类外函数只可读。

对常数据成员的初始化用构造函数的初始化列表。

const int Length;
Rectangle(int w,int len):Length(len)
{Width=w;}

(13)常成员函数

这些函数只是可读函数,不改变类的数据成员,对函数加上const关键字标识,提高程序的可读性。

#include<iostream>
#include<cstdio>
using namespace std; class Rectangle
{
private:
int width,length;
public:
Rectangle(int w,int len)
{
width=w;
length=len;
}
int area()const;
void print()
{
cout<<"print"<<endl;
}
}; int Rectangle::area()const
{
//width=10;不可修改数据成员
//print();常成员函数不能调用非const型成员函数
return width*length;
} int main()
{
Rectangle r(,);
cout<<r.area()<<endl;
return ;
}

(14)常指针

将指针变量声明为const,这样指针始终保持其初值,不会改变。

#include<iostream>
#include<cstdio>
using namespace std; class Rectangle
{
private:
int width,length;
public:
Rectangle(int w,int len)
{
width=w;
length=len;
}
int area()
{
return width*length;
}
}; int main()
{
Rectangle r1(,);
Rectangle *const ptr=&r1;
cout<<ptr->area();
// Rectangle r2(3,3);不可以改变常指针的值
// ptr=&r2;
return ;
}

(15)常引用

一个变量的引用就是这个变量的别名。

变量名和引用名都指向同一段内存单元。

如果形参为变量的引用名,实参为变量名,则在调用时虚实结合,

并不是为形参新开辟了空间,而是把实参变量地址传给形参。

如果不希望在函数中修改实参的值,则可以把引用变量名声明为常引用。

#include<iostream>
#include<cstdio>
using namespace std; class Rectangle
{
private:
int width,length;
public:
Rectangle(int w,int len)
{
width=w;
length=len;
}
void setWL(int w,int len)
{
width=w;
length=len;
}
int area()
{
return width*length;
}
}; void setRec(Rectangle &r1)
{
r1.setWL(,);
} int main()
{
Rectangle r(,);
cout<<r.area()<<endl;
setRec(r);
cout<<r.area()<<endl;
return ;
}

若是常引用,则不可以修改。

(16)友元

c++用关键字 friend声明类的友元

①位于一个函数说明语句之前,指出该函数为这个类的友元函数。

②位于一个类名之前,指出该类是这个类的友元。

如果要允许一个不属于类的函数取该类中的数据

法一:数据成员声明为共有

法二:将类内部声明这个函数为友元,可以访问该类数据。

后者更好。友元其实破坏了类的封装。

友元函数是普通(全局)函数

//友元
#include<iostream>
#include<cstdio>
using namespace std; class Rectangle
{
private:
int width,length;
public:
Rectangle(int w,int len)
{
width=w;
length=len;
}
int area()
{
return width*length;
}
friend void display(Rectangle &r1);
}; void display(Rectangle &r1)//必须要加&
{
cout<<r1.length<<" "<<r1.width<<endl;//不能直接使用length必须通过对象使用
cout<<r1.area()<<endl;
} int main()
{
Rectangle r(,);
display(r);
return ;
}

友元函数是其他类的成员函数

#include<iostream>
#include<cstdio>
using namespace std;
class Rectangle;//提前引用说明
class Cuboid
{
private:
int Height;
public:
Cuboid(int h)
{
Height=h;
}
int Volume(Rectangle &r);//此处只能声明,不能定义。因为Rectangle类还未定义
}; class Rectangle
{
private:
int width,length;
public:
Rectangle(int w,int len)
{
width=w;length=len;
}
friend int Cuboid::Volume(Rectangle &r);
}; int Cuboid::Volume(Rectangle &r)
{
return r.length*r.width*Height;
} int main()
{
Rectangle R(,);
Cuboid C();
cout<<"长方体的体积为:"<<C.Volume(R)<<endl;
return ;
}

(17)友元类

C++中允许将一个类声明为另一个类的友元,称为友元类。友元类中的所有成员

函数都可以访问另一个类中的私有成员或保护乘员

#include<iostream>
#include<cstdio>
using namespace std; class Rectangle; class Cuboid
{
private:
int Height;
public:
Cuboid(int h)
{
Height=h;
}
int Volume(Rectangle &r);
}; class Rectangle
{
private:
int width,length;
public:
Rectangle(int w,int len)
{
width=w;
length=len;
}
friend class Cuboid;
}; int Cuboid::Volume(Rectangle &r)
{
return r.length*r.width*Height;
} int main()
{
Rectangle r(,);
Cuboid C();
cout<<"长方体的体积为:"<<C.Volume(r);
return ;
}

(18)类模板

看不下去了。直接抄。

class A
{
private:
int x,y;
public:
A(int xx,int yy){x=xx;y=yy;}
int sum(){return x+y;}
}; class A
{
private:
double x,y;
public:
A(double xx,double yy){x=xx;y=yy;}
double sum(){return x+y;}
};

两段代码只是数据类型不同,但做的工作是重复的。

类模板是一系列相关类的模型或样板,这些类的成员组成相同,成员函数的源代码形式相同。所不同的只是类型。

(成员的类型以及成员函数的参数类型)。对于类模板,数据类型成了它的参数,因而是一种类型参数化的类。

类模板是类的抽象,类是类模板的实例。

template<class T>
class A
{
private:
T x,y;
public:
A(T xx,T yy){x=xx;y=yy;}
T sum(){return x+y;}
};

template<模板参数表>

class 类模板名

{}


class也可用typename关键字代替

类模板不能直接生成对象,因为其参数类型是不确定的,故需要首先对模板参数指定“实参”

类模板名<具体类型>对象名{(构造函数实参列表)}

A<int>IntA(6,8);

A<double>DoubleA(6.6,8.8)

若函数在类外定义

T A<T>::sum()

{return x+y;}

c++类的学习笔记的更多相关文章

  1. python 面向对象(类)--学习笔记

    面向对象是一种编程方式, 主要集中在类和对象的两个概念 python 中的类符合封装, 继承, 多态的特征 类 是一个模板, 是n多函数的集成 对象 是类的实例化 类的成员分为三大类:字段.方法.属性 ...

  2. Java sun.misc.Unsafe类的学习笔记

    Java未开源的Unsafe类 Unsafe类可以为我们提供高效并且线程安全方式操作变量,直接和内存数据打交道. 获取Unsafe实体的方法 private static Unsafe getUnsa ...

  3. 初步C++类模板学习笔记

    类模板 实现:在上课时间的定义给它的一个或多个参数,这些参数代表了不同的数据类型.                              -->抽象的类. 在调用类模板时, 指定參数, 由编 ...

  4. 初探C++类模版学习笔记

    类模板 实现:在定义类的时候给它一个或多个參数,这个些參数表示不同的数据类型.                              -->抽象的类. 在调用类模板时, 指定參数, 由编译系 ...

  5. 《C++ Primer Plus》14.4 类模板 学习笔记

    14.4.1 定义类模板下面以第10章的Stack类为基础来建立模板.原来的类声明如下:typedef unsigned long Item; class Stack{private:    enum ...

  6. JavaScript匿名类整理学习笔记

    以下为总结在开源的JavaScript框架中能看到很多这样语法结构(function(){})()比如我最近看的jQuery,及chediter.刚开始的时候我看到这样的结果有点奇怪,它是怎么执行的, ...

  7. 3.4常用类(java学习笔记)Math和Random

    一.Math 这个类包含执行指数.对数.平方根法.三角函数等基本的数字运算. Math中还包含一些静态常量供我们调用. 如PI圆周率,E. 1.abs(),返回该数的绝对值. public class ...

  8. UML类图学习笔记

    http://note.youdao.com/noteshare?id=d5af220db7081dda73511fcb7b4da390

  9. GUI学习之五——QAbstractButton类学习笔记

    今天总结一下AbstractButton类的学习笔记. 一.描述 AbstractButton是对各种按键的抽象类他的继承关系是这样的 首先,QAbstractButton继承了QWidget类的各种 ...

随机推荐

  1. 关于sublime建立python工程的说明

    https://www.zhihu.com/question/22681628此链接说明的不错,可以参考. 为了方便使用sublime,难免要定义一些快捷键,https://www.whidy.net ...

  2. 新工具解决消息丢失的bug

    最近在调查一个消息丢失的bug,所幸客户的文本文件里有丢失的记录,但在localdb文件里找不到. 我当时的想法是,在运行report的时候把丢失的记录从文本文件找出来,然后添加到localdb里,最 ...

  3. python接口自动化5-session关联

    前言 我们不难发现浏览器中存在着cookie缓存等,但我们在python中如果像浏览器这样的缓存,我们就很难的需要关联cookie或会话了. 但python的requests库,就封装了Session ...

  4. Java 异常面试问题与解答

    Java 提供了一种健壮且面向对象的方法来处理称为 Java异常处理的异常情况. 1. Java中的异常是什么? 异常是在程序执行期间可能发生的错误事件,它会破坏其正常流程.异常可能源于各种情况,例如 ...

  5. make 命令与 Makefile

    make 是一个工具程序,通过读取 Makefile 文件,实现自动化软件构建.虽然现代软件开发中,集成开发环境已经取代了 make,但在 Unix 环境中,make 仍然被广泛用来协助软件开发.ma ...

  6. Web前端——表单提交和Js添加选项

    表单 表单提交 表单提交之后会将表单的数据以get或post方式,传送到action要打开的页面 方式1: 使用提交按钮 <form action="" method=&qu ...

  7. IIS 上部署 ASP.NET Core 应用程序

    1.下载 .Net Core Runtime 和 Hosting Bundle 下载地址:https://dotnet.microsoft.com/download/dotnet-core 分别下载 ...

  8. fwrite(): send of 8192 bytes failed with errno=104 Connection reset by peer

    问题:fwrite(): send of 8192 bytes failed with errno=104 Connection reset by peer 问题描述 通过mysql + sphinx ...

  9. C# 结构与类

    结构是一种可以包含数据成员和方法成员的值类型数据结构.为结构分配数据时不需要从托管堆中分配内存,结构类型的变量直接包含了该结构的数据.结构中可以包含构造函数,常量,字段方法,属性,运算符,事件和嵌套类 ...

  10. python 生成 树状结构

    树状结构: 字典里只有一个键值对, key 为根, 值为一个列表, 列表里的某个或多个元素可以再进行分支(分支还是列表) 比如: 邮件的发件人, 收件人, 转发关系树状结构 forwarding_re ...