C++快速入门(一)
- oop
- 访问控制
- this指针:
- 程序结构
- 重载
- 构造函数
- 静态成员&&友员函数
- 运算符重载
class是对struct的扩展:
struct person {
char *name;
int age;
char *work;
void (*printInfo)(struct person *per);
};
函数实现:
void printInfo(struct person *per)
{
printf("name = %s, age = %d, work = %s\n", per->name, per->age, per->work);
}
使用:
struct person persons[] = {
{"zhangsan", 10, "teacher", printInfo},
{"lisi", 16, "doctor", printInfo},
};
persons[0].printInfo(&persons[0]);
persons[1].printInfo(&persons[1]);
写成C++将其改造:
class person {
public:
char *name;
int age;
char *work;
void printInfo(void)
{
printf("name = %s, age = %d, work = %s\n", name, age, work);
}
};
访问控制:
this指针:
访问其内部成员:
class Person {
private:
char *name;
int age;
char *work;
public:
void setName(char *name)
{
this->name = name;
}
};
使用:
Person per;
per.setName("zhangsan");
类和对象
程序结构03
class Person {
private:
char *name;
public:
void setName(char *name);
};
void Person::setName(char *name)
{
this->name = name;
}
多人代码的整合,namespace 还是非常有用的。可以很轻松的避免变量与函数一样的命名
namespace A {
class Person {
private:
char *name;
public:
void setName(char *name);
};
void printVersion(void);
}
namespace A {
void Person::setName(char *name)
{
this->name = name;
}
void printVersion(void)
{
printf("Person v1, by weidongshan\n");
}
}
A::Person per;
per.setName("zhangsan");
A::printVersion();
/* 把A::Person放入global namespace, 以后可以使用Person来表示A::Person */
using A::Person;
using A::printVersion;
Person per;
per.setName("zhangsan");
A::printVersion();
还可以:
using namespace A;
using namespace C;
Person per;
per.setName("zhangsan");
A::printVersion();
std是一个类(输入输出标准),它包括了cin成员和cout成员
#include <iostream>
std::cout<<" work = "<<work<<std::endl;
也可以:
using namespace std;
cout<<"name = "<<name<<endl;
重载
构造函数
类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。
class Person {
private:
char *name;
int age;
char *work;
public:
Person() {cout <<"Pserson()"<<endl;}
Person(char *name)
{
cout <<"Pserson(char *)"<<endl;
this->name = name;
}
void printInfo(void)
{
cout<<"name = "<<name<<", age = "<<age<<", work = "<<work<<endl;
}
}
int main(int argc, char **argv)
{
Person per("zhangsan", 16);
Person per2;
per.printInfo();
return 0;
}
Person per("zhangsan", 16);
Person per2; /* 调用无参构造函数 */
Person per3(); /* int fun(); */
Person *per4 = new Person;
Person *per5 = new Person();
Person *per6 = new Person[2];
Person *per7 = new Person("lisi", 18, "student");
Person *per8 = new Person("wangwu", 18);
per.printInfo();
per7->printInfo();
per8->printInfo();
delete per4;
delete per5;
delete []per6;
delete per7;
delete per8;
类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
Line(); // 这是构造函数声明
~Line(); // 这是析构函数声明
// 成员函数定义,包括构造函数
Line::Line(void)
{
cout << "Object is being created" << endl;
}
Line::~Line(void)
{
cout << "Object is being deleted" << endl;
}
当下面的代码被编译和执行时,它会产生下列结果:
Line line;
// 设置长度
line.setLength(6.0);
Object is being created
Length of line : 6
Object is being deleted
静态成员&&友员函数
静态数据成员的注意事项:
静态数据成员,不属于任何一个对象,它是属于类的。如果使用对象去访问静态数据成员,那么编译器只关心该对象的类型,不关心该对象是什么。
静态数据成员,必须要进行初始化,而且必须要在类的外部初始化(类声明指声明类的一个“尺寸”“规格”,但是不对他进行内存分配),最好是在类定义完后,接着就是初始化类的静态数据成员。初始化方式见上述的例子
不可以通过类名访问非静态成员变量,可以用类名或者对象名访问静态成员变量。访问方式不同(类名::静态成员变量名,对象名.静态成员变量名)
静态成员函数:
静态成员函数与其他类成员函数不同一点是:它的参数中不存在默认的this指针,例如一个普通的成员函数void a(),编译器对其进行编译时,它会被转换为:void a(Student * this),而静态成员函数就是少了这个this指针
因为没有this指针,所以静态成员函数不可以访问非静态成员(包括函数和变量)。
静态成员函数可以通过类名或者对象名进行调用,但是在最好是使用类名调用,因为使用对象名调用时,它还是只看该对象是什么类型,本质还是类名调用。
class Student
{
protected:
static int num; //声明静态数据成员
public:
Student()
{
num++;
}
static void print()
{
cout << num << endl;
}
};
int Student::num = 0; //静态数据成员必须在类外部初始化,
c++中友元函数:
1)C++中引入友元函数,是为在该类中提供一个对外(除了他自己意外)访问的窗口;
2)这个友元函数他不属于该类的成员函数,他是定义在类外的普通函数,只是在类中声明该函数可以直接访问类中的private或者protected成员。
friend <返回类型> <函数名> (<参数列表>);
使用友元函数注意的要点:
类中通过使用关键字friend 来修饰友元函数,但该函数并不是类的成员函数,其声明可以放在类的私有部分,也可放在共有部分。友元函数的定义在类体外实现,不需要加类限定。
一个类中的成员函数可以是另外一个类的友元函数,而且一个函数可以是多个类友元函数。
友元函数可以访问类中的私有成员和其他数据,但是访问不可直接使用数据成员,需要通过对对象进行引用。
友元函数在调用上同一般函数一样,不必通过对对象进行引用。
class persion{
public:
persion(char *pn);
//友元函数;
friend void setweigth(persion &p,int h);//注意,参数列表中一般会有一个引用类型的形参,原因参考上面的使用要点3和4;
}
//友元函数的具体实现:这里没有类限定例如 (perion::setweigth)这种形式,这里可以与上面的disp()做个对比,一个属于类的成员,有限定,不属于类的成员函数,没有加限定。
void setweigth(persion &pn,int w)
{
strcpy(pn.name,pn);//实现字符串复制
pn.weigth=w; //私有成员数据赋值
}
//调用实现setweigth(),与一般函数调用一致。
setweigth(p,60);
运算符重载
重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。
Box operator+(const Box&);
class Point {
private:
int x;
int y;
public:
Point()
{
cout<<"Point()"<<endl;
}
Point(int x, int y) : x(x), y(y)
{
cout<<"Point(int x, int y)"<<endl;
}
Point(const Point& p)
{
cout<<"Point(const Point& p)"<<endl;
x = p.x;
y = p.y;
}
~Point()
{
cout<<"~Point()"<<endl;
}
int getX(){ return x; }
int getY(){ return y; }
void setX(int x){ this->x = x; }
void setY(int y){ this->y = y; }
void printInfo()
{
cout<<"("<<x<<", "<<y<<")"<<endl;
}
Point operator+(Point &p)
{
cout<<"operator+"<<endl;
Point n;
n.x = this->x + p.x;
n.y = this->y + p.y;
return n;
}
/* Point p(1,2); ++p; */
Point& operator++(void)
{
cout<<"operator++(void)"<<endl;
this->x += 1;
this->y += 1;
return *this;
}
/* Point p(1,2); p++; */
Point operator++(int a)
{
cout<<"operator++(int a)"<<endl;
Point n;
n = *this;
this->x += 1;
this->y += 1;
return n;
}
int main(int argc, char **argv)
{
Point p1(1, 2);
Point p2(2, 3);
Point m, n;
m = p1 + p2; /* m = p1.operator+(p2); */
cout<<"add p1,p2 = "<<m<<endl;
cout<<"begin"<<endl;
m = ++p1; /* m = p1.operator++(); */
cout<<"m = "<<m<<" "<<"p1 = "<<p1<<endl;
cout << "******************"<<endl;
n = p1++; /* m = p1.operator++(0); */
cout<<"n = "<<n<<" "<<"p1 = "<<p1<<endl;
cout<<"end"<<endl;
return 0;
}