[Basic] Khai báo và định nghĩa biến trong C++

Khai báo (Declarations) và định nghĩa (definitions)

Declarations – Khai báo

  • Là câu lệnh thông báo của 1 định danh trong chương trình.
  • Một định danh ta có thể khai báo nhiều lần.
int Add(int a, int b); // forward declaration Add function

int Add(int a, int b); //forward declaration Add function lần 2

int Add(int a, int b); //forward declaration Add function lần 3

Khai báo nhiều lần chương trình không báo lỗi, tuy nhiên ta chỉ cần khai báo 1 lần.

Các trường hợp của Declarations:

  • Khai báo nguyên mẫu hàm (không có thân hàm)
int Add(int a, int b); //Declarations hàm add
  • Khai báo biến với từ khóa extern, không có khởi tạo giá trị ban đầu
extern int val; //Declarations biến val
  • static data member của class.

=> Phải định nghĩa và khởi tạo giá trị biến static bên ngoài class

class Myclass
{
   public:
      static int val; // Khai báo biến static của class
};

//Định nghĩa biến static 
int Myclass::val = 10;
  • Khai báo tên class
//forward declaration class
class T;

Definitions – Định nghĩa

  • Mới thực sự tạo ra bộ nhớ cho định danh.
  • Mỗi định danh chỉ được định nghĩa 1 lần duy nhất
int val = 10; //Definitions biến val

extern val1 = 10; //Definitions biến val1

//Definitions hàm Add
int Add(int val1, int val2)
{
   return val1 + val2;
}

Header file trong C++

  • Thường có phần mở rộng là .h
  • Dùng để khai báo nguyên mẫu hàm (forward declare) sử dụng trong nhiều file.

Include header file sử dụng dấu <header> và “header”

  • Sử dụng <header> compiler sẽ tìm header file trong thư mục hệ thống (system directories)
  • Sử dụng “Header” compiler sẽ tìm header lần lượt :
  1. Trong file chứa source của project
  2. Trong include path được cấu hình trong IDE,
  3. Trong thư mục hệ thống.

Cách viết 1 file header

  • Luôn luôn sử dụng header guards (giới thiệu bên dưới)
  • Không nên định nghĩa biến trong header file ngoại trừ biến const, chỉ nên sử dụng Declarations trong header (giải thích bên dưới)
  • Không nên định nghĩa hàm trong header file chỉ sử dụng forward declare (khai báo nguyên mẫu hàm) (giải thích bên dưới)
  • Mỗi header file nên làm 1 công việc cụ thể.
    Mỗi header file nên đi kèm với 1 file source (.cpp) cùng tên (VD : Person.h và Person.cpp)
  • Không #include file .cpp

Header guards

Mỗi định danh chỉ được định nghĩa (definitions) 1 lần duy nhất

=> Nếu định danh được định nghĩa nhiều hơn 1 lần sẽ xảy ra lỗi

Ví dụ:

Math.h

int getSquareSides()
{
   //TODO
   return 4;
}

Geometry.h: (include file Math.h)

#include "Math.h"

Main.cpp

#include "Math.h"
#include "Geometry.h"

int main()
{
   //TODO
   return 0;
}

File Math.h được sử dụng trong Geometry.h

Main.cpp sử dụng cả 2 file Math.hGeometry.h

Lúc này file Main.cpp

int getSquareSides() // include từ math.h
{
   //TODO
   return 4;
}
int getSquareSides() // include từ geometry.h
{
   //TODO
   return 4;
}
int main()
{
   //TODO
   return 0;
}

=> compile error vì hàm getSquareSides được định nghĩa 2 lần.

=> Để giải quyết vấn đề này ta dùng Header guards là sử dụng tiền xử lý có điều kiện để biên dịch

#ifndef SOME_UNIQUE_NAME_HERE
#define SOME_UNIQUE_NAME_HERE

// Khai báo và định nghĩa hàm.

#endif

File Math.h

#ifndef MATH_H
#define MATH_H
int getSquareSides()
{
   //TODO
   return 4;
}
#endif

Chú ý :

  • Header guards chỉ giải quyết được vấn để include nhiều lần trong 1 file source (.cpp)
  • Header guards KHÔNG thể giải quyết được vấn đề include trong nhiều file source (.cpp)

File Test.cpp

#include "Math.h"

File Main.cpp

#include "Math"

=> Biên dịch lỗi vì hàm getSquareSides() được đình nghĩa 2 lần trong 2 file Test.cpp và Main.cpp

=> Đề giải quyết vấn đề này ta làm:

  • Trong file header (.h) CHỈ khai báo hàm nguyên mẫu, khai báo biến.
  • Tạo file source (.cpp) định nghĩa hàm và định nghĩa biến trong file header.

Math.h // Chỉ khai báo nguyên mẫu hàm

#ifndef MATH_H
#define MATH_H
   
   //Khai báo nguyên mẫu hàm
   int getSquareSides();

#endif

Math.cpp

#include "Math.h"

//Định nghĩa hàm được khai báo nguyên mẫu trong file .h
int getSquareSides()
{
   //TODO
   return 4;
}

=> Các file muốn sử dụng hàm getSquareSides chỉ cần include file Math.h

Was this article helpful?

Leave A Comment?