C++開發EOS基礎指南之類與結構
阿新 • • 發佈:2018-10-26
namespace pri 銷毀 默認構造函數 cti 對象 成員函數 初始化 析構
C++是一種面向對象的編程語言。它有一個強大的繼承系統,私有和公共成員變量,以及通過成員初始化列表在構造函數中初始化它們的好方法。析構函數是構造函數的附件,允許你在對象被銷毀或超出範圍時運行代碼。今天讓我們創建一個簡單的CryptoCurrency
類,另外看看繼承。
// @url: https://repl.it/@MrToph/CPPBasics-Classes-1
#include <iostream>
#include <string>
#include <stdlib.h>
//自動解析std命名空間,所以我們可以寫字符串而不是std::string
using namespace std;
//聲明一個類。
//類通常在頭文件(.h或.hpp)中聲明。
class Currency
{
//默認情況下,成員變量和函數是私有的。
string name;
double priceInUSD;
//此後的所有成員都是公共的
//直到找到“private:”或“protected:”。
public:
//默認構造函數
Currency();
//另一個帶兩個參數的構造函數
Currency(const string &_name, const double price);
//成員函數聲明(要遵循的實現)
void setName(const string &dogsName);
void setPrice(double price);
//不修改對象狀態的函數應該標記為const。
//如果給定對象的const引用,則允許你調用它們。
void print() const;
//函數也可以在類體內定義。
//這樣定義的函數會自動內聯。
void bark() const { cout << name << " barks!\n"; }
// C++有析構函數。它們是建造者的標識當一個對象被刪除或超出範圍時調用它們。
virtual ~Currency();
}; //分號必須遵循類聲明。
//類成員函數通常在.cpp文件中實現。
Currency::Currency()
{
cout << "A currency has been created\n";
}
Currency::Currency(const string &_name, double price)
{
name = _name;
priceInUSD = price;
cout << name << " has been created with a price of " << price << "USD\n";
}
void Currency::setName(const string ¤cyName)
{
name = currencyName;
}
void Currency::setPrice(double price)
{
priceInUSD = price;
}
//請註意,僅在聲明中需要“virtual”,而不是定義。
void Currency::print() const
{
cout << name << " is at a price of " << priceInUSD << "USD\n";
}
Currency::~Currency()
{
cout << name << " has been hard forked!\n";
}
//struct與類相同,但它們通常僅用於封裝數據很少包含方法,在這些情況下更喜歡類
struct block_header
{
//默認情況下,結構字段是公共的
uint64_t timestamp;
uint64_t blockNumber;
//指向block_header對象的指針
block_header* prevBlock;
};
int main()
{
//這會運行默認構造函數
Currency bitcoin;
bitcoin.setName("Bitcoin");
bitcoin.setPrice(1E5);
bitcoin.print();
Currency eos("EOS", 100);
eos.print();
block_header genesis;
genesis.timestamp = 1528445288;
genesis.blockNumber = 0;
//沒有用戶定義構造函數的結構
//可以通過“aggregate initialization”初始化
block_header second{1528445288, 1, &genesis};
cout << "Timestamp of second block " << second.timestamp << "\n";
//或通過提供struct的字段名稱顯式它們需要與結構中定義的順序相同,但允許你跳過初始化值
block_header third{.blockNumber = 2, .prevBlock = &second};
// third.timestamp初始化為0
cout << "Timestamp of block after block #" << third.prevBlock->blockNumber << ": " << third.timestamp << "\n";
}
繼承
如果沒有強制性的Animal
類示例,繼承的簡介會是什麽?請註意,C++支持多重繼承,這是一種(有爭議的)功能,其中一個類可以同時從多個類繼承。在開發智能合約時,你可能永遠不需要它,所以讓我們看一下從單個類繼承的情況。
#include <iostream>
using namespace std;
class Animal
{
string name;
int weight;
public:
//默認構造函數將其值“delegates”給其他構造函數
Animal() : Animal("Peter", 80){};
//構造函數獲取名稱和權重並初始化
//具有使用相同名稱的“initializer list”的類成員
Animal(const string &name, int weight) : name(name), weight(weight)
{
// we already write the function body here
cout << name << " was created\n";
};
void setName(const string &dogsName);
string getName() const;
void setWeight(int weight);
//可以覆蓋的函數必須聲明為_virtual_
virtual void print() const;
//函數也可以在類聲明中定義
//但要小心,因為它們會自動內聯。
void eat() { weight += 5; }
//如果要派生類,析構函數應該是虛擬的;
//如果它不是虛擬的,那麽如果通過基類引用或指針銷毀對象,則不會調用派生類的析構函數。
virtual ~Animal();
};
void Animal::setName(const string &animalName)
{
name = animalName;
}
string Animal::getName() const
{
return name;
}
void Animal::setWeight(int animalWeight)
{
weight = animalWeight;
}
//“virtual”僅在聲明中需要,而不是在定義中。
void Animal::print() const
{
cout << name << " weighs " << weight << "kg\n";
}
Animal::~Animal()
{
cout << "Animal " << name << " died\n";
}
// Dog現在是Animal的子類,並繼承了Animal的成員。
//但是如果沒有getter,可能無法直接訪問私有成員或方法。
class Dog : public Animal
{
string breed;
public:
Dog(const string &name,int weight,const string &breed):Animal(name,weight),breed(breed)
{
cout << "Woof\n";
}
//被重載的虛擬方法應標記為重載。
void print() const override;
};
void Dog::print() const
{
//調用Animal的打印功能
Animal::print();
//無法直接訪問.name,因為它是私有的
//需要訪問public getter getName
cout << Animal::getName() << " is a " << breed << " dog\n";
}
int main()
{
Dog dog("Carl", 10, "Dackel");
dog.print();
}
C++開發EOS基礎指南之類與結構