このポインタ:(典型的な例を通して彼を知るために)
class Human
{
char fishc;
Human(char fishc);//构造函数
};
Human::Human(char fishc)//对构造函数进行初始化
{
fishc=fishc;//意图就是把这个传入参数赋值给这个上边类属性的fishc
}
//但是这样赋值的话,他们的名字一样,这样的话构造器就有可能认不出来,(因为他不知道你是要把属性去覆盖参数,还是把传入的参数去覆盖给属性,因为两者的名字一样,但是语法没有错。他们是两个不同区域的一个是传入的参数,一个是类的属性,(因为他们位于两个不同的区域,所以语法上没有错))
//所以怎么让构造器知道哪个是参数哪个是属性呢?这个时候就需要用到this指针。
this->fishc=fishc;//this指针是指向当前的类生成的对象//所以就很明显前者是类的属性,后边是参数。
//这样的话编译器就懂了,赋值操作符的左边将被解释为当前对象的fishc属性,右边将被解释为构造器的传入来的fishc的参数。
// PS:このポインターを使用する基本原則は、コードにあいまいさの隠れた危険がない場合、このポインターを使用する必要がないということです。
------------クラスの継承-------
継承メカニズムにより、プログラマーはクラスのスタック階層を作成でき、各サブクラスはその基本クラスで定義されたメソッドとプロパティを継承します。(元のメソッドを継承しながら、他のいくつかの属性メソッドを追加します)(既存のコードは、継承メカニズムを介してさらに拡張し、新しいプログラムに適用できます)
(1)それらはすべて動物のサブタイプです。Turtle andPigの基本クラスとしてAnimalを書くことができます。
継承されたクラスの構文:
//语法:
class SubClass:public Superclass{...}
//例子:
class Pig:public Animal{...}
基本クラスは、親クラスおよびスーパークラスとも呼ばれる他のクラスから派生できます。子クラスは、基本クラス(TurtleクラスやPigクラスなど)から派生したクラスです。
実装は次のとおりです。
#include<iostream>
#include<string>
class Anmial//声明一个基类
{
public:
std::string mouth;
void eat();
void sleep();
void drool();
};
//继承基类
class Pig:public Animal
{
public:
void climb();
};
class Turtle:public Animal
{
public:
void swim();
};
//对上述方法进行补充
void Animal::eat()
{
std::cout<<"我正在吃"<<std::endl;
}
void Animal::sleep()
{
std::cout<<"我正在睡觉"<<std::endl;
}
void Animal::eat()
{
std::cout<<"我正在流口水"<<std::endl;
}//上述把基类的三个方法给搞定了
//下面实现子类的方法(不管他们是基类还是父类,他们都是方法就按照类的方法实现来写)
void Pig::climb()
{
std::cout<<"我会爬树"<<std::endl;
}
void Turtle::swim()
{
std::cout<<"我会游泳"<<std::endl;
}
int main()
{
//对类进行实例化
Pig pig;
Turtle turtle;
pig.sleep();
turtle.sleep();
pig.climb();
turtle.swim();
}
------パラメータを持つコンストラクター----
//构造器带着输入参数
//1、声明
class Animal
{
public:
Animal(std::string thename);
std::string name;
};
class Pig:public Animal
{
public:
Pig(std::string thename);
};
//2、方法定义
Animal::Animal(std::string thename)
{
name=thename;
}
Pig::Pig(std::string thename):Animal(thename)//Pig的构造器继承Animal的构造器
{
}
Pigのメソッドは空であるため、Animalのメソッドから直接継承します。
- - - アクセス制御 - - - -
上記のクラスのすべてのメンバーは、public:ステートメントで宣言されます。
いわゆるアクセス制御とは、C ++がクラス内のメソッドと属性を保護する手段を提供することです。
- - - -カバー - - -
(これには共通の機能があり、クラスごとに異なる実装メソッドが必要です)これは、クラスでこのメソッドを再宣言することを意味し、その関数名とパラメーターの戻り値はまったく同じです(そうでない場合はオーバーロードされます)。
例:eatメソッドをAnimalに追加し、サブクラスでオーバーライドします。
-------オーバーロード方式--------
継承後にオーバーロードすることはできません。(サブクラスでオーバーロードすることはできません)
----友元-------
別のクラスがこのクラスのフレンドクラスであることを宣言します。フレンド関係はクラス間の特別な関係です。この特別な関係により、フレンドクラスは相手のパブリックメソッドとプロパティにアクセスできるだけでなく、友達は相手の保護された相手にアクセスできます。そしてプライベートメソッドとプロパティ。
フレンド関係を宣言するための構文は、クラス宣言のどこかにフレンドクラス**を追加することです(**は、フレンドが必要な別のクラスの名前を表します)。
このステートメントは、パブリック、保護、およびプライベートの段落のどこにでも配置できることに注意してください。(その後、2人は同じ人に相当します)
例:クラスLoversを定義します。2つのサブクラスBoyfriendとGirlfriendがあります。Loversクラスのメソッドkiss()およびask();サードパーティのOthersは、kiss()Girlfriendクラスのオブジェクトを必要としています。
#include<stdio.h>
#include<iostream>
class Lovers
{
public:
Lovers(std::string theName);//构造函数,就是给他命名
void kiss(Lovers* lover);//参数声明一个指针,
void ask(Lovers* lover,std::string something);
protected:
std::string name;
friend class others;//这时候others跟Lovers就是一对。
};
class Boyfriend:public Lovers
{
public:
Boyfriend(std::string theName);
};
class Girlfriend:public Lovers
{
public:
Girlfriend(std::string theName);
};
class Others
{
public:
Others(std::string theName);
void kiss(Lovers* lover);
protected:
std::string name;//Lover->name属于这个类的protected
};
Lovers::Lovers(std::string theName);
{
name=theName;//构造函数给它命名,也就是说我们造一个人出来的时候,
}
void Lovers::kiss(Lovers* lover)
{
std::cout<<name<<"亲亲"<<lover->name<<std::endl;
}
void Lovers::ask(Lovers* lover,std::string something)
{
std::cout<<Lover->name<<"帮我"<<something<<std::endl;
}
//子类
Boyfriend::Boyfriend(std::string name):Lovers(theName)
{
}
Girlfriend::Girlfriend(std::string name):Lovers(theName)
{
}
//友元类
Others::Others(std::string theName);
{
name=theName;//构造函数给它命名,也就是说我们造一个人出来的时候,
}
void Others::kiss(Lovers* lover)//这个里边的参数引用到了lover
{
std::cout<<name<<"吻一下"<<lover->name<<std::endl;//lover->name属于这个Lovers类的protected,不是这个类的子类根本访问不到,而others不是它的子类,所以理论上是访问不到的,这里因为上边是friend class others;所以可以访问到。
}
//主函数
int main()
{
Boyfriend boyfriend("A君");//造一个人出来给它命名叫做A君(构造函数)
Girlfriend girlfriend("B妞");//叫做B妞
Others others("路人甲");//others这个陌生人叫做路人甲
girlfriend.kiss(&boyfriend);//因为参数是指针所以传进去的应该是对象的地址
girlfriend.ask(&boyfriend,"拖地")
std::cout<<"传说中的友元类,路人甲出现了\n"<<std::endl;
others.kiss(&girlfriend);
return 0;
}
-------静的プロパティと静的メソッド-------
静的プロパティと静的メソッドを作成します。宣言の前に静的予約ワードを追加するだけです。
#include<string>
#include<iostream>
class Pet
{
public:
Pet(std::string theName);//带参数的构造器
~Pet();
static int getCount();//这里作为一个接口,用来给他由他生成的对象来获取他这个计数器
protected:
std::string name;
private://private是这个类里的方法才能够调用的,getCount()函数可以调用//private成员只有这个类里边的方法才能够访问它
static int count;//私有成员,一个count计数器
};
class Dog :public Pet//继承Pet类
{
public:
Dog(std::string theName);
~Dog();
};
class Cat :public Pet//继承Pet类
{
public:
Cat(std::string theName);
~Cat();
};
int Pet::count = 0;//这一句做了两件事;第一:让编译器为count这个变量的值分配内存;第二:这个变量因为是在静态存储区,他是把这个变量初始化为0;
Pet::Pet(std::string theName)//构造函数,当该构造函数被调用的时候说明这个宠物已经被建造出来了
{
name = theName;
count++;//那么这个计数器就加一
std::cout << "一只宠物变出来了,名字叫做:" << name << std::endl;
}
Pet::~Pet()//析构器
{
count--; //析构器说明这个宠物已经挂掉了,所以计数器要减掉
std::cout << name << "挂掉了" << std::endl;
}
int Pet::getCount()//这个接口函数getCount()的唯一作用,把这个count返回出来,把他拿到的这个私有成员返回出来,然后show出来
{
return count;//是为了任何代码都可以通过调用getCount()函数(因为是public)从而来读取该属性count的值(因为该值是private,所以对该属性只能是读不能是写,只有在Pet的析构函数和构造函数才能够对他进行写)
}
Dog::Dog(std::string theName) :Pet(theName)//Dog的构造器继承Pet的构造器
{
//std::cout<<"this:"<<this<<endl;//1生成一个dog对象之后就把this指针给打印出来//按此它生成一个dog对象的时候this指针应该是指向dog对象的。下边生成dog对象
}
Dog::~Dog()
{
}
Cat::Cat(std::string theName) :Pet(theName)
{
}
Cat::~Cat()
{
}
int main()
{
Dog dog("Tom");//整了一只狗dog叫做Tom(继承构造器的实现)//用Dog类生产出dog对象
Cat cat("Jerry");//整了一只猫叫做Jerry
std::cout<<"dog:"<<&dog<<std::endl;//2这里生成dog对象之后,我们把dog也给打印出来
std::cout << "已经诞生了" << Pet::getCount() << "只宠物!\n\n";//显示出来//getCount()函数调用私有成员count
{//注意这里的大括号,是有作用的。这里相当于是一个区域
Dog dog_2("Tom_2");//又整了一只狗
Cat cat_2("Jerry_2");//又整了一只猫
std::cout << "现在呢,已经诞生了" << Pet::getCount() << "只宠物!\n\n";
}//到此之前还剩下两只,因为大括号之后析构函数了,把宠物给毁掉
std::cout << "\n现在还剩下" << Pet::getCount() << "只宠物!\n\n";
return 0;//return 0的时候一只宠物都没有了,因为析构函数了,把宠物给毁掉
}
//上述1和2处打印的地址完全一样
結果:右側の結果は、メイン機能の中央にある中括弧を削除することです。
静的静的変数の詳細な説明:https://www.cnblogs.com/dc10101/archive/2007/08/22/865556.html
静的メンバーはすべてのオブジェクトで共有されるため、静的メソッドで非静的要素にアクセスすることはできません。
非静的メソッドは、クラスの静的メンバーにアクセスでき、クラスの非静的メンバーにもアクセスできます。
C ++メモリ割り当て方法の詳細な説明-ヒープ、スタック、空きストレージ領域、グローバル/静的ストレージ領域、および一定のストレージ領域:https://fishc.com.cn/blog-9-1097.html
thisポインタ:thisポインタは、クラスの自動的に生成され、自動的に非表示になるプライベートメンバーです。これは、クラスの非静的メンバー関数に存在し、呼び出された関数が配置されているオブジェクトのアドレスを指します。(つまり、各オブジェクトを生成すると、オブジェクトのアドレスを指すthisポインターが自動的に生成されます)オブジェクトが作成されると、オブジェクトのthisポインターは自動的にオブジェクトデータを指します。最初のアドレス。
#include<iostream>
class Point
{
private:
int x,y;
public:
point(int a,intb)
{
x=a;
y=b
}
void MovePoint(int a,int b)
{
x=a;
y=b;
}
void print()
{
std::cout<<"x="<<x<<"y="<<y<<endl;
}
};
int main()
{
Point point1(10,10);//用Point这个类生产出Point1这个对象。这个点的坐标在(10,10)这个位置
Point1.MovePoint(2,2);
point1.print();
return 0;
}
//当对象point1调用MovePoint这个成员的时候,(实时上我们生成point1这个对象的时候,就有一个this指针指向point1的地址),当他调用MovePoint这个函数的时候,即将point1对象的地址传递给this指针,(因为我们需要用到的是point1这个对象的成员,那我们就必须知道这个对象的地址,就必须传递给this指针)
//MovePoint函数的原型事实上应该是 void MovePoint(Point* this,int a,int b);他有三个参数,一个是隐含的this指针它指向Point对象(第一个参数是指向该类对象的一个指针,我们在定义成员函数时没看见是因为这个参数在类中是隐含的,是C++的一个规则,因为每一个都是默认添加进第一个规则)。
//这样子pOint1的地址就传递给this,所以在MovePoint()函数中便可以显示的写成void MovePoint(int a,int b)(this->x=a;this->y=b)(其实也可以x=a,这样编译器知道哪一个是参数哪一个是变量,用this做区分)
//我们这样就可以知道point1调用该函数后,也就是point1的数据成员被调用并更新了值。