类->类型;类描述抽象概念的;
对象->变量;对象描述客观实的;
在进行面向对象程序设计时要先声明类,再创建该类的对象。
为了方便讲述与理解这里我使用一个例题进行讲解吧。
求圆柱体的表面积与体积;
#include <iostream>
#include <cmath>
using namespace std;
class Point
{
public:
Point(double aa = 0, double bb = 0)
{
a = aa;
b = bb;
p = 3.14*pow(a,2);
c = 3.14 * 2*a;
}
double getVolume()
{
return p * b;
}
double getArea()
{
return 2*p+c*b;
}
private:
double a;
double b;
double c;
double p;
};
int main()
{
double x,y;
cin >> x>>y;
Point t1(x,y);
cout << t1.getArea() << " " << t1.getVolume();
return 0;
}
Point t1(x,y); 表示建立一个对象;
Point表示的是类名,必须是已经存在的类名才行;
t1表示对象名,自己起,起名规则与标识符相同;
而(x,y)实参,具体的一会再说;
t1.getArea()表示使用t1的getArea;
定义类时要将类的位置放到函数的上面,要不然程序跑到主函数时,找不到类;
class为关键词:管理类中默认权限。这里还有一个关键词为struct;这两个区别就是class默认权限是private,而struct默认为pubilc;
那么什么是权限呢?
class 类名
{
public:
公有数据成员;
公有成员函数;
protected:
保护数据成员;
保护成员函数;
private:
私有数据成员;
私有成员函数;
};
权限分为三种pubilc、protected、private;
pubilc:共有权限,不管是类内还是类外都可以访问到;
protected:保护权限,类内与派生类可以访问到;
private:私有权限,只有类内可以访问到;
C++提供了比结构体类型更加方便安全的类类型,类的定义一般分为说明部分和实现部分。
说明部分来说明该类中的成员:数据成员和成员函数,成员函数是对数据成员进行操作的;
实现部分对成员函数进行定义。
Point为类名,可随意定义,一般首字母要大写;
{};定义类与定义函数的区别是要在“}”后面加上一个“;”
1.定义数据成员时不能给数据成员赋初值。因为类是抽象的,只是一种类型,类中 的数据成员不占内存空间。
class Point
{
double z;
double a;
double x=10;//错误
double y=20;//错误
};
2.类的数据成员可以使用 C++基本数据类型、构造数据类型,还可以使用已定义完整的类类型。
class Point
{
double x;
double y;
};
class Circle
{
Point p;//定义了上面的point中的成员;
double r;
};
3.在正在定义的类中,因为该类还没有定义完整,所以不能定义该类类型的数据成员,只能定义该类类型的指针或引用成员。
class Point
{
double x;
double y;
Point p1;//错误
Point &p2;//正确
Point *p3;//正确
};
那么定义了数据成员不能赋值该如何使用呢?
成员函数的定义、声明格式与非成员函数(全局函数)的格式与用法基本一样,只是成员函数属于某 个类。成员函数的定义可以放在类中,也可以放在类外。
所有在类内部定义的函数都是内联函数,称为隐式定义。
内联函数在编译时使用函数体替换调用处的函数名,可以提高函数运行的速度,但是会增加编译的时间。
class Point
{
public:
返回值类型 函数名(形参)
{
函数的内容;
}
void SetPoint(double xx,double yy)
{
x=xx;
y=yy;
}
void Display()
{
cout<<"("<<x<<","<<y<<")"<<endl;
}
private:
double x;
double y;
};
在主函数或者自定义函数里时,使用某对象的Setpoint需要(实际函数),而Display()不用;
在类外定义函数体的格式如下:
返回值类型 类名::成员函数名(形参表)
{
函数体;
}
::是类的作用域分辨符,放在类名与成员函数之间,表明后面的成员函数属于前面的那个类。
但在类外定义时需要在函数定义的 头前加上关键字 inline,称为显示定义,这样做使代码书写更加清晰。
如果采用这种方式定义内联函数,类的声明和内联成员函数的定义要放在同一个文件中,否则在编译时无法进行代码置换。
例如:与上面的内联函数效果一样的例子,
class Point
{
public:
void SetPoint(double xx,double yy);
void Display();
private:
double x;
double y;
};
inline void Point::SetPoint(double xx,double yy)
{
x=xx;
y=yy;
}
inline void Point::Display()
{
cout<<"("<<x<<","<<y<<")"<<endl;
}
一般地按照习惯将成员放入private;函数放入public;
你一定发现了怎么有个函数没有返回值呢?这是一个特殊的函数--构造函数
构造函数是一种特殊的成员函数,函数名与类名相同,可以有任意类型的参数,但不能有返回值类型,在建立对象时自动调用,用于为对象分配空间并进行初始化。
这就是在最上面的例子中我的主函数中建立Point t1(x,y)时可以加(x,y)的原因.如何没有定义构造函数不可加上(x,y)这样的实参,就是要写成这样Point t1;
如果在定义类时,没有为类定义构造函数,编译系统就生成一个默认形式的隐含的构造函数,这个构造函数的函数体是空的,因此默认构造函数只为对象开辟空间,而不对数据成员赋初值。
这是有人发现了,为什么我的构造函数中里的形参要加上( =0 )这一步呢?
又是一个例子:
#include <iostream>
using namespace std;
class Point
{
public:
Point(double xx=0, double yy=0)
{
x = xx;
y = yy;
}
void setPoint(double xx, double yy)
{
x=xx;
y=yy;
}
void displayPoint()
{
cout << "(" << x << ","<<y << ")" << endl;
}
private:
double x;
double y;
};
int main()
{
double x,y;
cin>>x>>y;
Point p;
p.displayPoint();
p.setPoint(x,y);
p.displayPoint();
return 0;
}
这里在建立对象时,没有给进实参,所以构造函数就会调用形参中的赋值进入形参里面;
如果不写=0,系统会报错,为啥呢?因为在建立一个对象后,我又使用了一个类里的函数,这个函数的功能是输出数据成员,而这时数据成员没有值,数据成员为抽象的,没有值就会报错,所以输出不了,就无法使用这个函数;
那么我可不可以这样定义呢?
Point(double xx, double yy)
{
xx=0;
yy=0;
x = xx;
y = yy;
}
当然不行了!!!因为数据成员时不能给数据成员赋初值;
又又人发现了,你最上面的例子不对啊,为啥构造函数里的形参(=0)和实参都写了。这样写是不算错的,实参有数据,成员函数的形参会忽略掉形参里的赋值,效果等于没有形参的(=0);
这时又又又注意到了,为什么成员函数的形参不像自定义函数里的形参似的可以设置成与实参一样的变量呢?
哈哈又是一个例子:
#include <iostream>
using namespace std;
class Point
{
public:
Point(double x, double y)
{
x = x;
y = y;
}
void displayPoint()
{
cout << x <<" "<<y<< endl;
}
private:
double x;
double y;
};
int main()
{
double x,y;
cin>>x>>y;
Point p(x,y);
p.displayPoint();
return 0;
}
如果设成这样会报错吧?当然不会啦!!!但是当你跑起程序时,你会发现输出的值不是你想要的,而是一堆乱码。为啥呢,因为我们编译器搞不明白x=x是哪两变量,是新参还是数据函数,就会造成程序错误。那怎么解决呢?
this 指针是一个系统预定义的特殊指针,指向当前对象,只能在类的成员函数中使用, 存有当前对象的地址,程序员不能改变,只能使用。
成员函数的形参名与数据成员名相同时,访问数据成员需要在数据成员前用 this 指针;
Point(double x,double y)
{
this->x=x;
this->y=y;
}
这样编译器就会明白了第一个x是数据成员,第二个x是形参中的x;
[1]CSDN:C++ class 和 struct 构造函数
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]