c++类

来源:互联网 发布:知达常青藤中学校官网 编辑:程序博客网 时间:2024/06/06 00:24

一、对象和类

1、构造函数

1.1  C++ 提供两种使用构造函数来初始化对象的方式:

1)   Class class=Class(p1 , p2,...);

2)   Class class(p1,p2,...);

这两种方式是等价的


与new(动态分配内存)一起使用:

Class *p = new Class(p1,p2...);

我们可以通过指针来管理该对象


1.2 默认构造函数

如果一个类没有提供任何构造函数,c++将自动提供默认构造函数,例如 

Class class ;  //使用的默认构造函数

当我们提供了任何非默认构造函数(例如:Class(p1)),但没有提供默认构造函数,则上面的定义就会出错。

在设计的类的时候,通常应该提供对所有成员变量做隐式初始化的默认构造函数

下面举个例子:

//Class.h#ifndef CLASS_H#define CLASS_H#include <iostream>class Class{ private:  int m_a;  int m_b; public:  Class()  {    std::cout<<"默认构造函数"<<std::endl;    m_a=10;    m_b=10;  }  Class(int,int);  ~CLass(){    std::cout<<"bye~  "<<m_a<<std::endl;  }  void show();};#endif

//Class.cpp#include <iostream>#include "Class.h"void Class::show(){  std::cout<<"m_a:"<<m_a<<"  m_b:"<<m_b<<std::endl;}Class::Class(int a,int b){  std::cout<<"构造函数"<<std::endl;  m_a=a;  m_b=b;}

//main.cpp#include <iostream>#include "Class.h"using namespace std;int main(){  Class a;  //print 默认构造函数  a.show();  // m_a:10  m_b:10  a=Class(1,2);  //构造函数  a.show();   //m_a:1  m_b:2  Class b(3,4);  //隐式形式  b.show();       Class* c=new Class(); //默认构造函数  Class* d=new Class;   //默认构造函数  Class e=Class();      //默认构造函数  Class f();  //声明一个函数,  }

定义在类声明中的函数,都将自动成为内联函数

2、析构函数

析构函数没有参数

静态存储类对象,在程序结束时候,自动调用;自动存储类型,将在程序执行完该代码块的时候,自动调用;通过 new 创建的,当时候delete的时候调用。

还是用上面的类,改一下main方法,

//main.cpp                                                                                                                                                                                                   #include <iostream>#include "Class.h"using namespace std;Class g(1,1);void fun1(){  cout<<"fun1()"<<endl;  a.show();}int main(){  cout<<"main()"<<endl;  fun1();  Class *p=new Class(30,30);  delete p;  return 1;}

运行结果:


可以看出,在main函数开始前,就构造了Class g,并且在整个程序结束的时候,自动调用其析构函数

在执行fun1()的时候,构造了Class a,并且在该函数结束的时候,自动调用其析构函数

我们是用new的方法构造了指向一个Class 的指针p, 并手动调用delete 的时候,调用其析构函数

3、this指针

类中中到每个成员函数都(包括构造和析构函数)都有一个 this指针,指向调用对象。

3.1 成员函数后面加const

有 const 修饰的成员函数(指 const 放在函数参数表的后面,而不是在函数前面或者参数表内),只能读取数据成员,不能改变数据成员;没有 const 修饰的成员函数,对数据成员则是可读可写的。除此之外,常量(即 const)对象可以调用 const 成员函数,而不能调用非const修饰的函数。

4、类到作用域

4.1 在类中定义常量,使用关键字 static,该常量将于其他静态变量存储在一起,而不是在存储在对象中。

4.2 作用域内枚举

    当在相同到作用域中,两个枚举定义中到枚举量会产生冲突:如 

enum A { One,Two,Three};

enum B {One,Two,Three};

c++11 提供了一种新的枚举量到作用域为类

enum class A {One ,Two,Three};

enum class B {One,Two,Three};

这样就可以使用下面方法访问

A a = A::One;

B b = B::One;


二、类的使用

2.1 运算符重载

    c++允许将运算符重载扩展到用户自定义到类型,例如,允许使用 + 将两个对象相加。编译器将根据操作数和类型决定使用哪种加法定义。

    重载运算符到格式L operatorOP (...)  其中OP必须是有效到C++运算符,例如 +,-,*,[]

 例子还是上面的Class 类,不过我们新加运算符重载的方法

Class Class::operator+(const Class & t) const{    int a=(*this).get_a()+t.get_a();  int b=(*this).get_b()+t.get_b();  /*  Class *res=new Class(a,b);  std::cout<<res<<std::endl;  return *res;  */  Class ret=Class(a,b);  return ret; }

main函数:

//main.cpp#include <iostream>#include "Class.h"using namespace std;int main(){  Class *p=new Class(30,30);  Class *q=new Class(40,40);  Class  n=*p+*q;  n.show();  cout<<&n<<endl;}


注意:注释掉的代码是为脑洞大开想到,这样到结果是,析构函数只调用了一次,(因为*p *q没有时候delete方法,所以不会调用他们到析构函数),并且operator+函数里面到地址和main里面不一样,为个人估计,这样到用法结果就是内存泄漏,因为operator 中到指向堆到指针在函数结束到时候,就被回收掉了,那么就再也没有指针指向堆中到那个地址


2.2 友元函数

这里暂且先介绍函数《其他还有友元类等)

关键字: friend

可以赋予函数与类到成员函数相同到访问权限。也就是可以访问私有属性

前面重载中我们知道

A=B+2;将被转换成下面到成员函数调用:

A=B.operator+(2);

但是如果是:

A=2+B; 呢?

因为2不是对象,所以编译器不能使用成员函数调用来替换这个表达式,但是我们有另外一种方式:非成员函数,只要我们有一个 operator+(2 , B);就可以了

这样只要在Class 中声明一个友元函数 operator(int ,Class & );

下面结合重载,写一个常用到的例子

2.2.1 重载<<运算符

首先定义Class类

//Class.h#ifndef CLASS_H#define CLASS_H#include <iostream>using namespace std;class Class{ private:  int m_num; public:  Class(){}   Class(int num);  int get_num(){return m_num;}  friend ostream & operator<<(ostream & os , const Class & c);  };#endif

//Class.cpp#include "Class.h"Class::Class(int num){  m_num=num;}ostream & operator<<(ostream & os ,const Class & c){   os<<"num is:"<<c.m_num;  return os;}

注意:1.ostream 也是在std命名空间里面

            2. 只用传引用就可以了,为了说明不改变 Class中到属性,所以用const

            3. 我们返回ostream引用,这样就支持  std::cout<<A<<B;的格式

           4.只在类声明原型中才能使用 friend关键字,除非声明的时候同时也定义,否则不能在函数定义中使用friend关键字(编译器会报‘friend’ used outside of class)

我们写一个简单到main函数

#include <iostream>#include "Class.h"using namespace std;int main(){  Class c(10),d(20);  cout<<"Class c:"<<c<<" and  Class d:"<<d<<endl;  //Class c:num is:10 and  Class d:num is:20}感觉作用就像java里面重载toString一样,这样就可以自己写一个类的输出打印到信息 


0 0