1. 类
*在C++中,struct和class没有明显差别,不同C#,class一定要new(手动开辟内存)出来
struct Hero
{
  char name[64];
  int sex;
}
void print(struct Hero &h)
{
...
}
class AdvHero
{
  public:
  char name[64];
  int sex;
  void print()
  {
    cout<<name<<endl;
  }
}
int main(void)
{
  Hero h;
  strcpy(h.name,"zhangsan");
  //
  AdvHero v;//不用new出来,c++中的new另有含义
  strcpy(v.name,"lisi");
}

2. 构造函数:
class A
{
  public:
    int age;
    char* Name;
    A(int x)
    {
      age=x;
      Name =(char*)malloc(100);
    }
    ~A()
    {
      //析构函数没有形参,当对象被销毁前自动调用
      if(name!=NULL)
      {
        free(name);
      }   
    }
}
int mian()
{
  A a(10);
}
//堆栈在a被声明时,在栈中,开辟存储a的内存,含有一个int大小的,和char*一个指针大小的空间,然后在堆中,开辟100个字节的空间,用Name指向它。
//但是析构的时候,只会自动清除栈的东西,所以一定要记得释放堆中的东西。
//栈是会被压的!!

拷贝构造函数:
class Test
{
  //显式的拷贝构造函数,
  Test(const Test &anthor)//const引用,就是不能改变anthor所代表的对象的任何东西。
  {
    //...
  }
  //=赋值操作符
  void operator=(const Test &another)
  {
    //...
  }
}
//和C#不同,C#是没有拷贝构造函数的。
//
int main(void){
  Test t1;
  Test t2(t1);
  //这句话,如果=号操作没有重载,拷贝构造函数也没有重载,那么也相当于t2=t1;t1复制一份,给t2。
  //就算Test没有传入参数为Test的构造函数,也能成功。能自动将成员值拷贝过去。
  //因为有默认的拷贝构造函数
  Test t3;
  t3=t1;//这里就不是调用构造函数了,而是调用=操作函数
  //
  Test t4=func();//**这里也不会发生t4先构造,然后执行=操作,而是将func()返回的结果“转正”
  //
  t3=func();//**这里就会发生执行=操作了。而且func()返回的匿名对象会被析构掉。

}
******************************
//在C++中,struct和class没有明显差别。不同C#,class一定要new(手动开辟内存)出来。
//在classA a;这句中,已经调用了构造函数了。C#中,仅仅是声明一个空的引用变量a。
//在a=b;调用了操作符号=函数。C#中,则是引用变量a来引用b引用的对象,a和b都是引用同一个对象。
//所以C++中,对象的传参,参数返回(除非是返回堆中的对象引用),都是复制的操作,同时,复制的时候会调用默认的拷贝构造函数,出栈的时候,也会调析构函数。
//各种拷贝,析构,也是可以通过引用来优化的地方!
//这是C++和大多数语言的不同。
******************************

3. 深拷贝和浅拷贝
class Teacher
{
  int m_id;
  char*m_name;
  public:
    Teacher(int id,char *name)//这就算深拷贝了,浅拷贝的话,m_name的值和name是一样,指向同一块内存。
    {
      m_id=id;
      int len = strlen(name);
      m_name=(char*)malloc(len+1);//因为最后要以\0标志字符串结束,所以+1
      strcpy(m_name,name);
    }
    //一般的浅拷贝构造函数
    Teacher(const teacher&a)
    {
      mid=a.mid;
      m_name=a.m_name;
    }
    //一般的浅拷贝构造函数
    Teacher(const teacher&a)
    {
      //按Teacher(int id,char *name)来写。
    }
    ~Teacher()
    {
      if(m_name!=NULL)
      {
        free(m_name);//记得释放堆上的内存
      }
    }
}
//*****free是不能重复对同一指针值(内存地址)执行两次的。
//*****所以,见到类中,有指针成员,一定要特别留意,先看析构函数,会不会有可能free同一个内存地址;然后考虑要不要深拷贝。
//*****浅拷贝风险,就是有指针成员时,析构时释放堆内存,可能会重复释放内存。

4. 构造函数的初始化列表
class B
{
  public:
    B(A &a1,A&a2,int m):m_a1(a1),m_a2(a2),m_m(m)//常量成员的赋值,只能放在初始化列表中
    {
      //如果这使用m_a1=a1,显然达不到调用A的构造函数的目的,只是调了A的=操作符函数
      //如果这里写m_a1(a1),会语法错误,将m_a1当做了函数使用了
    }
  private:
    A m_a1;
    A m_a2;
    int a=3;//很多编译器不支持这种写法,所以尽量要写到构造函数中
    const int m_m;//只能赋值一次,而且不能const int m_m=3;因为有些编译器不支持
}
//在构造的时候,先执行A的构造两次,然后执行B构造函数体;在析构的时候,先析构m_a1和m_a2,然后再执行B析构的函数体。

5. 静态成员
void test()
{
    int static a=10;//这句话只会在第一次执行的时候,给a赋值,因为a在运行初阶段就放在静态区了。
    a++;
}

class A
{
  public:
    A()
    {
      //...
    }
    static int m_c;//也是在程序运行之初放在静态区的
}
**************************************************************
int AA::m_c=100;//在声明类的时候,就给静态变量赋初值了。
*记得#ifndef #endif

void funtion()
{
  AA:m_c=100;//不用写成 int AA:m_c=100;这是在方法之外写的。
}

6. this指针
//对于一个类,只有非静态字段才属于这个对象(才在这个对象的内存中),static成员在静态区,而且方法也不在这个对象的内存区域中。
//那为什么a.getPrivateProperty()能获得a的私有成员呢,但是getPrivateProperty()方法不在a的内存区域内???
class Test
{
  private:
    int n1;
    public:
      Test(int i)
      {
        n1=i;
      }
      int getn1()
      {  
         return n1;
         //等价于return this->n1;
      }

      int getn2() const //加个const,防止这个方法内改变this所指向的内容,相当于const Test * const this(指向常量的常指针,相当于常引用了)
      {
      }

      static void print()
      {//...}
}

int main(void){

  Test a(10);
  a.getn1();
  Test::Print();

}

通过编译后,变为:
struct Test
{
  int n1;
};
void Test_initialize(struct Test *pThis,int i)
{
  pThis->n1=i;
}
int Test_getn1(struct Test *pThis)
{
  return pThis-<n1;
}
void Test_Print(){//.....}

int main{
  Test a;
  Test_initialize(&a,10);
  Test_getn1(&a);
  Test_Print();

}
//再次,在C++中,struct和class没有明显差别。

7. 返回对象本身,主要可以用于链式操作
class Test
{
  private :
    int a;
  public:
    &Text Add(Text &another)
    {
      this->a=this->a+another.a;
      return *this;
    }
}
//能达到每次连加都会改变自身,又不用复制。

8. 友元函数
class Point
{
  private :
    double x;
    double y;
    //
    friend double PointDistance(const Point &p1,const Point &p2);
    //也能friend double Calculater::PointDistance(const Point &p1,const Point &p2);
    //Calculater类一定要在Point声明之前声明好
  public:
    Point(double x,double y)
    {
      this->x=x;
      //...
    }
    double getX()
    {
      return this->x;
      //以匿名的方式,返回x的复制值。
    }
    double getY(){ //...}
}
double PointDistance2(const Point &p1,const Point &p2)
{
  //有getX(),getY()的操作,调用方法就有压栈出栈的过程,效率比p1.x低多了。
}

如果在类中声明有:
friend double PointDistance(const Point &p1,const Point &p2); 那么就可以p1.x,使用私有成员了。就像PointDistance是类中的成员函数一样。
**因为友元通常会破坏封装性,所以不推荐使用。

9. 声明。声明的作用,就是预先告知有这个东西,其地方要使用它,必须要有预先告知。比如:
  double PointDistance2(const Point &p1,const Point &p2);
如果这个函数声明前,没有通过头文件,或者其他办法,获取到Point 的声明,那么编译不过的。
正确的办法:
  class Point;//这个也是声明
  double PointDistance2(const Point &p1,const Point &p2);
****这也是C#和C++不同的地方,C#是声明和实现放在一起,而且不分先后顺序。

10. 友元类
class B;
  class A
  {
    friend class B;
    priviate : int a;
  }
class B
{
  private : int b;
  public:
    B& addA(const A &a)
    {
      this->b= this->b+a.a;
      return *this;
    }
}
**因为友元通常会破坏封装性,所以不推荐使用。

11. 操作符重载
//
new和delete也是操作符,也能重载的
//
*通常会重载“=”号,用于深拷贝
*通常也会重载+-号,用于一些字段的加减
class Complex
{
   private:
    int a;
    int b;
   public:
    Complex operator +(const Complex &b)
    {
      Complex c;
      c.a=this->a+b.a;
      c.b=this->b+b.a;
      return c;
    }
        //如果写在外边的话Complex operator +(const Complex &a, const Complex &b); 调用也可以Complex c3= operator+(c1,c2);

    Complex& operator +=(const Complex &b)
    {
      c.a=this->a+b.a;
      c.b=this->b+b.a;
      return this;
    }

    //后++运算,加const,防止拼命++下去
    const Complex operator ++(int)//要有个int填坑
    {
      Complex temp(*this);
      this.a++;
      this.b++; 
      return temp;
    }
    //为了能cout << complex,但这里c1.operator<<(os);或者c1<<cout;太别扭
    //所以只能写全局了
    ostream & operator <<(ostream &os)
    {
      os<<this->a<<this->b;
      return os;
    }
}

ostream & operator <<(ostream &os,Complex &c);//这样就可以cout<<c了;

12. 任何传入类的字符串指针,都要考虑深拷贝和析构,否则如果外边释放了内存,那么使用会出错。

13. ***************************重写无参构造,=操作符必要的注意事项***************************
等号操作符注意事项:
class A
{
  public:
    char*Name;
    A(const A &a)
    {
      this->name=new char[strlen(a.Name)];
      if(this->name!=NULL){
        strcpy(this->Name,a.Name);
      }
    }
    //遇到有成员指针是开辟堆内存的,一定要重写=,重写无参构造,重写析构
    A & operator=(const A &a)
    {
      if(this==*a) { return *a;}
      //
      if(this->name!=NULL)
      {
        delete[] this->name;
        this->name = NULL;
      }
      //重新开辟
      this->name=new char[strlen(a.Name)];
      if(this->name!=NULL){
          strcpy(this->Name,a.Name);
      }
    }
    ~A()
    {
      if(this->name==NULL)
      {
        delete[] this->name;
        this->name = NULL;
      }
    }
}

14. []操作符重载,通常返回引用,因为a[i]应该既可以取,也可以修改才行。
char & operator[](const int &i)
{
  return this->Name[i];
}

15. ()操作符重载
int main(void)
{
  typeA a ;
  a();//这里是由于操作符重载,所以可以这样
}

16. const引用和const函数
class A
{
  public:
    int getLenght1()//实际上会编译为 int getLenght(int *const this),const指针,指向不可变
    {

    }
    //
    int getLenght2() const //实际上为const int *const this,相当于const引用,指向内容不可变,指向不可变 , 相当于const A &a
    {

    }
}

// 不能通过const引用修改变量的值
void function(const A &a) //为了保护a不在方法中被改变
{
  a.getLenght1(); //这里出错,用高安全的引用作为实参,调用低安全形参的函数。
  a.getLenght2(); //这里才不会出错
}

17.  类模板

C#

public class Airport<T> where T:Plane  //能限定T的类型

{

  //..

}

template<class T> class Person

{

  public:

    T mId;

    T mAge;

    Person(T mld,TmAge);

    template<class T> friend ostream& operator<<(ostream& os,Person<T> &p);//windows下

      friend ostream& operator<<<T>(ostream& os,Person<T> &p);//linux下

}

//声明和实现分开

temple<class T> Person<T>::Person(T mld,TmAge)//十分麻烦的写法

{

}

//

template<class T> ostream& operator<<(ostream& os,Person<T> &p)

{

}

最好的写法:

//

template<class T> class Person;//先额外声明

template<class T>void Print(Person<T> &p);//先额外声明

template<class T> Person

{

  public :

    friend void Print<T>(Person<T> &p);

}

//

template<class T>void Print(Person<T> &p)

{

  //....

}

//

继承

class SubPerson:public Person<int>

{

}

18.  类模板的声明部分和实现部分分离,然后使用的坑

//C++编译器,对cpp文件独立编译,不会看文件之间的关联有没有出错

//C++编译器在编译的时候,发现一个函数调用,在当前文件找不到,那么先留坑,让后面连接器找。

//模板类,会进行两次编译,第一次对模板;第二次,在发现调用的时候,再去找模板,再编译多一个具体的函数出来。

(include<头文件>只做内容替换,不编译)

//所以,函数模板的实现部分,一定要在使用前先编译好。那么:可以不包含头文件,直接包含源文件

#include "Person.cpp"

//还有业界的做法就是,不要声明和实现分离,将他们写到Person.hpp;那么别人就知道是模板了。

19. 模板类的静态成员

根据上边的结论

template <class A>  class P

{

  public:

    static int a;

}

template <class A> P::a=1;

//

int main()

{

  P<int> a;

  P<char> b;

  //a.a和b.a不是共享同一个a,因为由于模板的编译方式,P<int>和P<char>可以当做两个类

}

C++学习笔记3_类.和相关函数的更多相关文章

  1. Java学习笔记——File类之文件管理和读写操作、下载图片

    Java学习笔记——File类之文件管理和读写操作.下载图片 File类的总结: 1.文件和文件夹的创建 2.文件的读取 3.文件的写入 4.文件的复制(字符流.字节流.处理流) 5.以图片地址下载图 ...

  2. APUE学习笔记3_文件IO

    APUE学习笔记3_文件IO Unix中的文件IO函数主要包括以下几个:open().read().write().lseek().close()等.这类I/O函数也被称为不带缓冲的I/O,标准I/O ...

  3. python学习笔记4_类和更抽象

    python学习笔记4_类和更抽象 一.对象 class 对象主要有三个特性,继承.封装.多态.python的核心. 1.多态.封装.继承 多态,就算不知道变量所引用的类型,还是可以操作对象,根据类型 ...

  4. Java学习笔记之---类和对象

    Java学习笔记之---类和对象 (一)类 类是一个模板,它描述一类对象的行为和状态  例如:动物类是一个类,动物们都有属性:颜色,动物们都有行为:吃饭 public class Dog { Stri ...

  5. UML学习笔记:类图

    UML学习笔记:类图 有些问题,不去解决,就永远都是问题! 类图 类图(Class Diagrame)是描述类.接口以及它们之间关系的图,用来显示系统中各个类的静态结构. 类图包含2种元素:类.接口, ...

  6. swift学习笔记3——类、结构体、枚举

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  7. Java学习笔记-File类的基本方法

    要渐渐养成写博客的习惯-----> 前段时间看Mars的java中的I/O流没怎么懂,发现I/O流好难啊.今天重新看一遍其他教学,还有书籍,做些笔记,记录下每天的学习生活. File类的一些方法 ...

  8. CSS3学习笔记——伪类hover

    最近看到一篇文章:“Transition.Transform和Animation使用简介及应用展示”    ,想看看里面 “不同缓动类效果demo”例子的效果,发现了一个问题如下: .Trans_Bo ...

  9. Java7编程 高级进阶学习笔记--嵌套类

    定义: 在一个类中定义的类叫做嵌套类. 作用: 1.允许对相关类进行逻辑分组 2.增强了代码的封装性 3.使代码具有更强的可读性和维护性 使用方式: package com.cmz.baseTest; ...

随机推荐

  1. Android资源管理利器Resources和AssetManager

    前言  : Android工程在运行的时候往往需要引用资源.使用 Resources 来获取 res 目录下的各种与设备相关的资源.而使用 AssetManager 来获取 assets 目录下的资源 ...

  2. .Net Core Serverless初体验

    什么是Serverless Serverless 是一个当今软件世界中比较新的话题.它并没有一个普遍公认的权威定义,每个人每个企业对它的解释可能都有不同,而 Serverless 正是在这种情况下不断 ...

  3. asp.net 开源工作流-ccflow关于 “ 是否自动计算未来的处理人”的功能变更

    关键字:流程未来节点处理人  工作流快速开发平台  工作流流设计  业务流程管理   asp.net 开源工作流 业务背景:一个流程在启动起来后,是可以对一些节点计算出来处理人是谁,流程的走向.对于另 ...

  4. 无意间做了个 web 版的 JVM 监控端(前后端分离 React+Spring Boot)

    之前写了JConsole.VisualVM 依赖的 JMX 技术,然后放出了一个用纯 JMX 实现的 web 版本的 JConsole 的截图,今天源码来了. 本来就是为了更多的了解 JMX,第一步就 ...

  5. 什么是Cookie?——每日一题20190623

    什么是Cookie? Cookie实际上是一小段的文本信息,客户端请求服务器,如果服务器需要记录该用户状态,就使用 response 向客户端浏览器颁发一个Cookie.客户端会把Cookie存起来, ...

  6. BUUCTF刷题记录(Web方面)

    WarmUp 首先查看源码,发现有source.php,跟进看看,发现了一堆代码 这个原本是phpmyadmin任意文件包含漏洞,这里面只不过是换汤不换药. 有兴趣的可以看一下之前我做的分析,http ...

  7. Java集合总结—再也不怕面试问到集合了

    Java集合总结 1.常见的集合 Map接口和Collection接口是所有集合框架的父接口: Collection接口的子接口包括:Set接口和List接口 Map接口的实现类主要有:HashMap ...

  8. Python从入门到精通视频(全60集) ☝☝☝

    Python从入门到精通视频(全60集) Python入门到精通 学习 教程 首先,课程的顺序需要调整:一和三主要是介绍学习和布置开发环境的,一介绍的是非VS开发,三介绍的是VS开发.VS2017现在 ...

  9. 基于Prometheus和Grafana的监控平台 - 环境搭建

    相关概念 微服务中的监控分根据作用领域分为三大类,Logging,Tracing,Metrics. Logging - 用于记录离散的事件.例如,应用程序的调试信息或错误信息.它是我们诊断问题的依据. ...

  10. Redis学习三(进阶功能).

    一.排序 redis 支持对 list,set 和 zset 元素的排序,排序的时间复杂度是 O(N+M*log(M)).(N 是集合大小,M 为返回元素的数量) sort key [BY patte ...