随意记录一下,不一定按照课程顺序和章节顺序来。以前接触过一些c,但是好久不用,有些忘记了,复习一些细节和重要的c++知识。为了能够更好学习Geant4。
每个视频都在讲C++是一个面向对象的语言,具有封装性,继承性和多态性。感觉这句话可能需要对C++有一定掌握了才能够比较好地理解。
之前有听到过一个对C++是一个面向对象的语言的一个通俗的解释,比如:描述我们洗浴的过程,去浴室用水龙头洗,洗完擦拭干净就结束了。如果要用面向对象的语言描述:①对象:浴室门打开 ②对象:水龙头打开 ③对象:人洗浴 ④对象:毛巾擦拭。这里边有四个对象,每个对象都有自己的属性和行为。如:门{ 木制,可旋转,接通和阻断空间;开/关 } ;毛巾{布的,吸水;使用吸水特性}等等,我们进入浴室时就要调用门的旋转特性打开它让人能够进入;洗浴完成后又需要调用毛巾的吸水特性来擦干。
类和对象
一、类的定义
类:具有相同属性(数据)和行为(函数)的一组对象的集合,它为属于该类的全部对象提供了统一的抽象描述,其内部包含属性和行为两个主要部分。利用类可以实现数据的封装、隐蔽、继承和派生。
类简单来说,就是属性和方法的集合,属性就是类中的数据,方法就是调用这些属性数据进行操作的函数。
class classname
{
//成员变量
//成员函数
public: //公有访问限定
公有成员(外部接口)
private: //私有访问限定
私有成员
protect:
保护型成员
};//要写分号
类成员函数的两种定义方法:
A:声明和定义都放在类体当中
class classname
{
//在类体内定义和声明函数
public:
void SetClock(int h,int m,int s)
{
.........函数的具体定义..........
}
};
B:声明和定义分开,类体内声明,类体外进行函数定义。(推荐)
class classname(Clock)
{
//在类体内声明函数,在类外定义函数。
public:
void SetClock(int h,int m,int s)
};
//类外定义函数:在函数前,加类名、以及限定符::。
void Clock::SetClock(int h,int m,int s)
{
.........函数的具体定义..........
}
二、类的访问限定符和封装
1、访问限定符:public private protect
公有成员在public后面声明,是类与外界的接口,任何外部函数都可以访问公有成员(数据和函数);私有成员在private后面声明,只允许本类中的函数访问,而类外部的任何函数都不能访问。保护类型的成员在protect后面声明,类外部的任何函数都不能访问,但是可以被继承。
public: //公有成员在public后面声明,是类与外界的接口
成员数据
成员函数
private: //私有访问限定
私有成员
protect:
保护型成员
访问限定域:从访问限定符出现的位置到下一个访问限定符结束。
class的默认访问权限为private , struct默认为public
2、封装
面向对象的三个特性:封装、继承、多态
封装本质上是一种管理手段,将属性(数据)和方法(接口)有机结合起来,再隐藏他们,之对外公开接口和对象进行交互。主要是因为class和访问修饰符的设计(public,private,protect)和只读(get)只写函数(set)。
3、对象
类的对象是该类对象的某一特定实体。
声明形式: 类名 对象名:
类中成员互相访问:直接使用成员名
类外访问:“对象名.成员名”而且是public成员。
三、class B:A 类的继承
class B : public A 是类的继承关系,即A类是B类的基类,类B继承于类A。
当B继承A的时候,自动地将父类中所有的public成员继承了。
class Fruit
{
};
class Apple : public Fruit
{
};
//然后就可以在代码中使用子类定义对象了。
Apple A;
A.weight = 500*g
A.taste = "sweet"
//子类需要的成员中,父类有的内容就可以不用在定义了,没有的成员可以再定义。
//子类需要的成员中,父类有的内容就可以不用在定义了,没有的成员可以再定义。public可以被继承,而private不能被继承,也不能被外部访问。public不能被访问,但可以被继承。
class <派生类名>:<继承方式><基类名>
{
<派生类新定义成员>
};
虚拟继承和虚拟函数virtual
子类可以继承父类的成员函数,但是,如果子类想改写父类中的某个成员函数的话,要怎么办呢?
子类可以重写这个函数:
class Parent
{
public:
void Test();
};
class Child : public Parent
{
public:
void Test(); //子类可以重写这个函数
};
int main()
{
Child ch;
ch.Test();
return 0;
}
如果要重写父类的成员函数时,我发现,父类的成员函数还有部分可用,要怎么办?
class Parent
{
public:
void Test();
};
class Child : public Parent
{
public:
Parent::Test(); //先调用一下父类的函数即可
void Test(); //子类可以重写这个函数
};
父类的指针指向子类的对象,是可以的:
int main()
{
Child ch;
Parent* p = &ch; //父类的指针指向一个子类的对象
p->Test();
return 0;
}
思考一下,这个p->Test()会输出什么?
结果是输出父类的Test()的结果,如果我想要输出子类的改写的成员函数的结果,要怎样做?
当一个成员函数需要子类重写时,那么在父类中应该将其声明为virtual,作用是根据对象的实际类型,调用相应类型的函数。
class Parent
{
public:
virtual void Test(); //在父类的成员函数前加virtual;
};
class Child : public Parent
{
public:
void Test(); //子类可以重写这个函数
};
C++的一些简单知识
一、C++文件的编译运行:
C++编辑软件一般会带有编译器,进到编译器的Bin目录,复制地址,添加到环境变量中。然后去到.cpp文件所在的目录,在路径输入框中输入cmd,会进入到该目录的命令窗口,然后输入:
g++ 01.cpp 在该目录下会生成一个a.exe的文件。
g++01.cpp -o 01.exe 那么在该目录下生成一个01.exe的文件。
编译好后就可以运行了,在命令窗口输入:01.exe
二、输入输出
C++并未提供任何的输入输出语句,但是拥有一个全面的标准库来提供输入输出机制。比如:iostream库,其中包含两个基础的类型istream和ostream。
cin 读取数据
cout 输出数据 ; 输出还有cerr和clog,这两个一般会用在大型的程序中,用于输出错误。
# 预处理指令
#include <iostream>
int main()
{
std::cout << "Enter two numbers:" << std::endl; //std::endl屏幕刷新和换行的意思。
int v1 = 0, v2 = 0;
std::cin >> v1 >> v2;
std::cout << "The sum of " << v1 << " and " << v2 " is " << v1 + v2 << std::endl;
return 0;
}
std是一个标准命名空间,cout是std下的一个操作符,需要用调用符(作用域运算符)::来调用cout ;命名空间可以帮助我们避免不经意的名称定义冲突,以及使用库中相同名字导致的冲突。
注释
// 单行注释 ; 快捷键 ctrl+/
/* 多行注释,快捷键选中多行,ctrl+/
*……
*/
三、头文件和源文件
一般后缀为 .h 的文件是头文件,内部包含函数声明、宏定义、结构体定义等内容。
后缀为 .c 的文件是源文件,内部包含函数实现、变量定义等内容。
头文件是源文件的辅助文件,include是一个预编译指令,后面一般不写分号,这个辅助文件可以是头文件也可以是其他任意格式的文件 .h .c .cpp
为防止头文件的重复包含,我们应该加上头文件的保护:
#ifndef _OBJECT_H
#define _OBJECT_H //为防止多次包含头文件
........
#endif
#include "...h" 原理
预编译指令,编译器在处理每个cpp文件之前,首先进行一个预处理,将所有的#include替换成该头文件的具体内容,然后在进行整体的编译。
一个cpp文件要调用另一个cpp文件中的函数或者使用另一个cpp文件中的全局变量:
extern: 声明外部函数或者声明外部全局变量。extern的作用,告诉编译器,在某个cpp文件中,存在这样一个函数/全局变量。
extern double a //告诉编译器存在一个全局变量a
extern double arr[5] //告诉编译器存在一个全局数组arr ,外部声明不可以初始化
extern double get_area(double r);
extern int sum(int a, int b);