C++使用初始化列表的方式来初始化字段

时间:2022-04-29 01:27:11

几个月之前,接触Android recovery源代码的时候,看ScreenRecoveryUI类的时候,那时候C++基础还不是特别好,一直不明白以下的初始化方式:

下面这个是Recovery的一个构造函数,代码位于:screen_ui.cpp,它的类的实现在screen_ui.h。

如下这个ScreenRecoveryUI类,这个类是继承于RecoveryUI类的:

这个文件在screen_ui.h

class ScreenRecoveryUI : public RecoveryUI {
public:
ScreenRecoveryUI();

void Init();
void SetLocale(const char* locale);

// overall recovery state ("background image")
void SetBackground(Icon icon);

// progress indicator
void SetProgressType(ProgressType type);
void ShowProgress(float portion, float seconds);
void SetProgress(float fraction);

void SetStage(int current, int max);

// text log
void ShowText(bool visible);
bool IsTextVisible();
bool WasTextEverVisible();

// printing messages
void Print(const char* fmt, ...) __printflike(2, 3);
void ShowFile(const char* filename);

// menu display
void StartMenu(const char* const * headers, const char* const * items,
int initial_selection);
int SelectMenu(int sel);
void EndMenu();

void KeyLongPress(int);

void Redraw();

enum UIElement {
HEADER, MENU, MENU_SEL_BG, MENU_SEL_BG_ACTIVE, MENU_SEL_FG, LOG, TEXT_FILL, INFO
};
void SetColor(UIElement e);

private:
Icon currentIcon;
int installingFrame;
const char* locale;
bool rtl_locale;

pthread_mutex_t updateMutex;
GRSurface* backgroundIcon[5];
GRSurface* backgroundText[5];
GRSurface** installation;
GRSurface* progressBarEmpty;
GRSurface* progressBarFill;
GRSurface* stageMarkerEmpty;
GRSurface* stageMarkerFill;

ProgressType progressBarType;

float progressScopeStart, progressScopeSize, progress;
double progressScopeTime, progressScopeDuration;

// true when both graphics pages are the same (except for the progress bar).
bool pagesIdentical;

size_t text_cols_, text_rows_;

// Log text overlay, displayed when a magic key is pressed.
char** text_;
size_t text_col_, text_row_, text_top_;

bool show_text;
bool show_text_ever; // has show_text ever been true?

char** menu_;
const char* const* menu_headers_;
bool show_menu;
int menu_items, menu_sel;

// An alternate text screen, swapped with 'text_' when we're viewing a log file.
char** file_viewer_text_;

pthread_t progress_thread_;

int animation_fps;
int installing_frames;

int iconX, iconY;

int stage, max_stage;

void draw_background_locked(Icon icon);
void draw_progress_locked();
void draw_screen_locked();
void update_screen_locked();
void update_progress_locked();

static void* ProgressThreadStartRoutine(void* data);
void ProgressThreadLoop();

void ShowFile(FILE*);
void PutChar(char);
void ClearText();

void DrawHorizontalRule(int* y);
void DrawTextLine(int* y, const char* line, bool bold);
void DrawTextLines(int* y, const char* const* lines);

void LoadBitmap(const char* filename, GRSurface** surface);
void LoadBitmapArray(const char* filename, int* frames, GRSurface*** surface);
void LoadLocalizedBitmap(const char* filename, GRSurface** surface);
};
下面是这个类的构造函数的实现,其中构造函数就采用了初始化列表的方式来初始化字段,以下构造函数的实现在screen_ui.cpp文件中可以找到。

ScreenRecoveryUI::ScreenRecoveryUI() :    currentIcon(NONE),    installingFrame(0),    locale(nullptr),    rtl_locale(false),    progressBarType(EMPTY),    progressScopeStart(0),    progressScopeSize(0),    progress(0),    pagesIdentical(false),    text_cols_(0),    text_rows_(0),    text_(nullptr),    text_col_(0),    text_row_(0),    text_top_(0),    show_text(false),    show_text_ever(false),    menu_(nullptr),    show_menu(false),    menu_items(0),    menu_sel(0),    file_viewer_text_(nullptr),    animation_fps(20),    installing_frames(-1),    stage(-1),    max_stage(-1) {    for (int i = 0; i < 5; i++) {        backgroundIcon[i] = nullptr;    }    pthread_mutex_init(&updateMutex, nullptr);}
可以来看看RecoveryUI类:

在ui.h中:

class RecoveryUI {  public:    RecoveryUI();    virtual ~RecoveryUI() { }    // Initialize the object; called before anything else.    virtual void Init();    // Show a stage indicator.  Call immediately after Init().    virtual void SetStage(int current, int max) = 0;    // After calling Init(), you can tell the UI what locale it is operating in.    virtual void SetLocale(const char* locale) = 0;    // Set the overall recovery state ("background image").    enum Icon { NONE, INSTALLING_UPDATE, ERASING, NO_COMMAND, ERROR };    virtual void SetBackground(Icon icon) = 0;    // --- progress indicator ---    enum ProgressType { EMPTY, INDETERMINATE, DETERMINATE };    virtual void SetProgressType(ProgressType determinate) = 0;    // Show a progress bar and define the scope of the next operation:    //   portion - fraction of the progress bar the next operation will use    //   seconds - expected time interval (progress bar moves at this minimum rate)    virtual void ShowProgress(float portion, float seconds) = 0;    // Set progress bar position (0.0 - 1.0 within the scope defined    // by the last call to ShowProgress).    virtual void SetProgress(float fraction) = 0;    // --- text log ---    virtual void ShowText(bool visible) = 0;    virtual bool IsTextVisible() = 0;    virtual bool WasTextEverVisible() = 0;    // Write a message to the on-screen log (shown if the user has    // toggled on the text display).    virtual void Print(const char* fmt, ...) __printflike(2, 3) = 0;    virtual void ShowFile(const char* filename) = 0;    // --- key handling ---    // Wait for a key and return it.  May return -1 after timeout.    virtual int WaitKey();    virtual bool IsKeyPressed(int key);    virtual bool IsLongPress();    // Returns true if you have the volume up/down and power trio typical    // of phones and tablets, false otherwise.    virtual bool HasThreeButtons();    // Erase any queued-up keys.    virtual void FlushKeys();    // Called on each key press, even while operations are in progress.    // Return value indicates whether an immediate operation should be    // triggered (toggling the display, rebooting the device), or if    // the key should be enqueued for use by the main thread.    enum KeyAction { ENQUEUE, TOGGLE, REBOOT, IGNORE };    virtual KeyAction CheckKey(int key, bool is_long_press);    // Called when a key is held down long enough to have been a    // long-press (but before the key is released).  This means that    // if the key is eventually registered (released without any other    // keys being pressed in the meantime), CheckKey will be called with    // 'is_long_press' true.    virtual void KeyLongPress(int key);    // Normally in recovery there's a key sequence that triggers    // immediate reboot of the device, regardless of what recovery is    // doing (with the default CheckKey implementation, it's pressing    // the power button 7 times in row).  Call this to enable or    // disable that feature.  It is enabled by default.    virtual void SetEnableReboot(bool enabled);    // --- menu display ---    // Display some header text followed by a menu of items, which appears    // at the top of the screen (in place of any scrolling ui_print()    // output, if necessary).    virtual void StartMenu(const char* const * headers, const char* const * items,                           int initial_selection) = 0;    // Set the menu highlight to the given index, wrapping if necessary.    // Returns the actual item selected.    virtual int SelectMenu(int sel) = 0;    // End menu mode, resetting the text overlay so that ui_print()    // statements will be displayed.    virtual void EndMenu() = 0;protected:    void EnqueueKey(int key_code);private:    // Key event input queue    pthread_mutex_t key_queue_mutex;    pthread_cond_t key_queue_cond;    int key_queue[256], key_queue_len;    char key_pressed[KEY_MAX + 1];     // under key_queue_mutex    int key_last_down;                 // under key_queue_mutex    bool key_long_press;               // under key_queue_mutex    int key_down_count;                // under key_queue_mutex    bool enable_reboot;                // under key_queue_mutex    int rel_sum;    int consecutive_power_keys;    int last_key;    bool has_power_key;    bool has_up_key;    bool has_down_key;    struct key_timer_t {        RecoveryUI* ui;        int key_code;        int count;    };    pthread_t input_thread_;    void OnKeyDetected(int key_code);    static int InputCallback(int fd, uint32_t epevents, void* data);    int OnInputEvent(int fd, uint32_t epevents);    void ProcessKey(int key_code, int updown);    bool IsUsbConnected();    static void* time_key_helper(void* cookie);    void time_key(int key_code, int count);};
ui.cpp中,也是采用字段初始化的方式来实现构造函数:

RecoveryUI::RecoveryUI()        : key_queue_len(0),          key_last_down(-1),          key_long_press(false),          key_down_count(0),          enable_reboot(true),          consecutive_power_keys(0),          last_key(-1),          has_power_key(false),          has_up_key(false),          has_down_key(false) {    pthread_mutex_init(&key_queue_mutex, nullptr);    pthread_cond_init(&key_queue_cond, nullptr);    memset(key_pressed, 0, sizeof(key_pressed));}

现在看明白了。

写一个测试案例看看就懂了,果然一例解千愁啊!

#include <iostream>using namespace std ;class ScreenRecoveryUI {private :int r , g , b ; char buffer[10] ;char *p ;public :ScreenRecoveryUI();void setvalue(int a , int b , int c);void print();};//使用初始化列表的方式初始化构造函数里的私有环境变量 ScreenRecoveryUI::ScreenRecoveryUI():r(0),g(0),b(0),p(nullptr){for(int i = 0 ; i < 10 ; i++){buffer[i] = 0 ;}} void ScreenRecoveryUI::setvalue(int a ,int b , int c){this->r = a ; this->g = b ; this->b = c ;}void ScreenRecoveryUI::print(){cout << "r:" << this->r << endl << "g:" << this->g << endl << "b:" << b << endl ;  }int main(void){ScreenRecoveryUI screen ; screen.setvalue(255,255,0);screen.print();return 0 ;}
运行结果:

r:255

g:255

b:0