一、 条件语句if + 布尔值
falls = true;
if (!falls) {
// 这里的代码块不会被执行,因为 !falls 是 false
}
当你有一个布尔变量,比如 falls = true;,然后使用 if (!falls) 进行判断时,!falls 将会对 falls 的值取反。所以,如果 falls 的值为 true,!falls 就会变成 false。if语句将不会运行。
二、类成员函数
例1
void Carbon::report_car(Type flux_type, int pft_id, double value) {
annual_carbon_per_pft[pft_id][flux_type] += value;
}
Carbon::report_car 是C++中表示类成员函数的语法,它可以分解成三个部分:Carbon、::、和 report_car。
1.Carbon 是一个类的名称。在C++中,类是一种用户定义的数据类型,用于封装数据和函数操作。类定义了一个对象的结构和行为。
2.:: 是作用域解析运算符,它用于指定类的成员函数属于哪个类。在 Carbon::report_car 中,Carbon 是类的名称,report_car 是该类的成员函数。:: 表示 report_car 是 Carbon 类的一部分。
3.report_car 是类 Carbon 中的一个成员函数。成员函数是与类关联的函数,它可以访问类的成员变量和其他成员函数。在这个例子中,report_car 是在 Carbon 类中声明和定义的一个函数,它可能用于报告某种通量(flux)的信息。
综合起来,Carbon::report_car 表示 report_car 是属于 Carbon 类的成员函数。这个成员函数可以通过 Carbon 类的对象来调用,用于执行特定于该类的操作。
例2
double Soil::get_soil_water_layer1() const {
return get_soil_water(0, blayer1);
}
①Soil::get_soil_water_layer1() const:
这是一个成员函数的定义,属于 Soil 类。它返回一个双精度浮点数 (double),表示土壤的水分含量。
②return get_soil_water(0, blayer1);:
在函数体中,它调用了 get_soil_water 函数,该函数接受两个参数(0 和 blayer1)。这两个参数被用来指定土壤剖面的深度范围。具体来说,它表示从土壤的表面到 blayer1 所代表的深度的土壤层。
③const 关键字:
const 关键字在函数声明的末尾表示该函数是一个常量成员函数,意味着在函数体内,它不能修改调用它的对象的成员变量。
引申-const用法
const 是C++语言中的一个关键字,用于定义常量。在不同的上下文中,const 可以用于不同的用途。在例2中,const 出现在函数声明的末尾,表示这是一个常量成员函数。
在C++中,const 的使用有以下两种主要情况:
1.常量变量:
const int myConstVariable = 10;
在这个例子中,myConstVariable 被声明为一个常量,其值不能被修改。
2.常量成员函数:
double MyClass::getSomeValue() const {
// 函数体
}
在这个例子中,const 出现在成员函数的声明末尾,表示这是一个常量成员函数。常量成员函数有以下特点:
①它不修改调用它的对象的成员变量。在函数体内,不能修改类的非静态成员变量。
②它可以被常量对象调用。如果一个对象是常量(用 const 修饰),则只能调用它的常量成员函数。
对于例2
double Soil::get_soil_water_layer1() const {
return get_soil_water(0, blayer1);
}
在这里,const 表示 get_soil_water_layer1 是一个常量成员函数。这意味着在函数体内,它不能修改 Soil 类的成员变量。这种设计有助于确保常量成员函数不会对对象状态进行修改,从而使其更适合用于常量对象。
三、C++中的接口类
在C++中,接口类通常是一种抽象类,其主要目的是定义一组纯虚函数(pure virtual functions)。这些纯虚函数在接口类中没有具体的实现,而是由派生类提供具体的实现。接口类用于定义一些规范或者契约,要求派生类必须按照这些规范提供特定的功能或行为。
1.声明纯虚函数:
在接口类中声明一组纯虚函数,这些函数没有具体的实现,以 = 0 结尾表示。
class Interface {
public:
virtual void doSomething() = 0;
virtual int calculateValue() const = 0;
// 更多的纯虚函数声明...
};
1.1纯虚函数
virtual int calculateValue() const = 0;
这段代码表示在C++中的一个虚函数声明,其中,
①virtual 关键字:表示这是一个虚函数,可以在派生类中被重写。
②int:表示函数返回类型为整数。
③calculateValue:是函数的名称。
④() const:表示这是一个不修改对象状态的成员函数。const 限定符表明该函数不会修改对象的成员变量,它是一个常量成员函数。
⑤= 0:表示这是一个纯虚函数。纯虚函数是在基类中声明但没有提供实现的虚函数,它要求派生类必须提供具体的实现。派生类如果不提供对纯虚函数的实现,那么它也会变成一个抽象类,无法实例化对象。
2.派生类实现
派生类继承接口类,并提供具体的实现。
class ConcreteClass : public Interface {
public:
void doSomething() override {
// 具体的实现...
}
int calculateValue() const override {
// 具体的实现...
int result = /* 具体计算逻辑 */;
return result;
}
};
在C++11及以后的版本中,override 关键字用于显式地指示编译器某个成员函数是在派生类中重写(覆盖)了基类中的虚函数。这是一种声明的方式,用来确保代码中的重写操作是符合预期的。
3.实例化对象
可以通过接口类指针或引用来使用派生类的对象。
Interface* obj = new ConcreteClass();
obj->doSomething();
int value = obj->calculateValue();
delete obj;
通过这样的方式,接口类允许在整个代码中定义一致的接口,并确保派生类按照这个接口提供实现。这在实现多态、代码模块化和代码组织方面都很有用。
在这段代码中,Interface* obj = new ConcreteClass(); 的含义是创建了一个指向 ConcreteClass 对象的指针,该指针的类型是 Interface*。这是一种典型的多态使用方式。
具体解释:
①Interface* obj:声明了一个指针变量 obj,其类型为 Interface*,意味着它可以指向任何派生自 Interface 类的对象。
②new ConcreteClass():动态地在堆上创建了一个 ConcreteClass 对象,并返回该对象的地址。由于 ConcreteClass 是 Interface 的派生类,所以可以用 Interface* 类型的指针来指向它。
③obj = new ConcreteClass();:将刚刚创建的 ConcreteClass 对象的地址赋给 obj 指针,这样 obj 就指向了这个对象。
④obj->doSomething();:通过指针调用了 doSomething 函数。这里使用箭头操作符 -> 是因为 obj 是一个指针,而不是对象本身。-> 用于通过指针访问对象的成员函数或成员变量。
⑤int value = obj->calculateValue();:同样使用箭头操作符,调用了 calculateValue 函数。
⑥delete obj;:释放了通过 new 创建的对象的内存。这是因为使用 new 在堆上创建对象时,需要手动释放相应的内存,以防止内存泄漏。
整个过程体现了多态性,即通过基类指针 Interface* 调用派生类对象的函数,而具体调用的是派生类中实现的版本。这种机制允许你以统一的方式操作不同派生类的对象,而无需知道对象的具体类型。