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

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

(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. 【python爬虫】cookie & session

    一.什么是cookie? cookie是指网站为了鉴别用户身份,进行会话跟踪而存储在客户端本地的数据. 二.什么是session? 本来的含义是指有始有终的一些列动作,而在web中,session对象 ...

  2. OC:浅析Runtime中消息转发机制

    一.介绍 OC是一门动态性语言,其实现的本质是利用runtime机制.在runtime中,对象调用方法,其实就是给对象发送一个消息,也即objc_msgSend().在这个消息发送的过程中,系统会进行 ...

  3. Java设计模式:Simple Factory(简单工厂)模式

    概念定义 简单工厂(Simple Factory)模式,又称静态工厂方法(Static Factory Method)模式,即定义一个工厂类,根据传入的不同参数创建不同的产品实例,这些实例对象具有共同 ...

  4. WebSocket数据加密——AES与RSA混合加密

    前言 之前在写“一套简单的web即时通讯”,写到第三版的时候没什么思路,正好微信公众号看到一篇讲API交互加密,于是就自己搞了一套AES与RSA混合加密,无意中产生应用在WebSocket想法,好在思 ...

  5. C#判断dataGridView1 点击的是哪一列上的按钮

    private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) { ) { DataGr ...

  6. Implement Custom Business Classes and Reference Properties 实现自定义业务类和引用属性(XPO)

    In this lesson, you will learn how to implement business classes from scratch. For this purpose, the ...

  7. 在Vue-cli3.x中引入element-ui的新方式

    今天登上element官网,发现element对vue-cli3.x的项目做了特殊定制: 这意味着即使是按需引入,也无需像过去那样手动安装babel-plugin-component,配置babel. ...

  8. Windows10下安装解压版MySQL教程

    MySQL安装分为安装版和解压版,安装版主要是由一个exe程序式安装,有界面鼠标点击安装即可,小白建议使用安装版安装mysql,相比较与安装版,解压版安装更"纯净",没有多余的东西 ...

  9. 「SAP技术」 SAP MM MPN物料的采购初探

    「SAP技术」 SAP MM MPN物料的采购初探 1, MPN物料号与我方正常使用料号物料主数据之间的LINK关系维护 MPN料号 14000005 , 我方料号11000250 , 2,采购信息记 ...

  10. 微信小程序使用weui构建搜索栏(searchbar)+导航(navbar)

    首先需要在lib目录中添加weui.wxss.searchbar和navbar结合主要解决两者的层次问题,即搜索框输入时,下方的检索结果能够覆盖住navbar.下面就开始发码啦: (1)wxml部分: ...