C++์์์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น
LHS์ RHS
LHS๋ left-hand-side expression, RHS๋ right-hand-side expression์ด๋ค. ๊ตณ์ด ์ด๋ ต๊ฒ ์๊ฐํ์ง ์๊ณ , ํํ์์์ ์ผ์ชฝ์ ํ ๋น๋ฐ๋ ์ฃผ์ฒด๋ฅผ LHS๋ผ๊ณ ํ๊ณ , ํ ๋นํ๋ ๋์์ RHS๋ผ๊ณ ํ๋ค.
z = x+y๋ผ๋ ์์ด ์๋ค๋ฉด, LHS๋ z๋ผ๊ณ ํ๊ณ , x+y๋ RHS๋ผ๊ณ ํ๋ค.
C++์์์ ๋ฉ๋ชจ๋ฆฌ ๋ชจ๋ธ
- &x (RHS์์๋ง ์ฌ์ฉ)
- ๋ณ์ x์ ์ฃผ์๋ฅผ ๋ฆฌํดํ๋ค.
- x (RHS์ ๊ฒฝ์ฐ)
- ๋ณ์์ ์ฃผ์์ ํ ๋น๋ ๊ฐ์ ๋ฆฌํดํ๋ค.
- x (LHS์ ๊ฒฝ์ฐ)
- ๋ณ์์ ์ฃผ์์ RHS ๊ฐ์ ์ ์ฅํ๋ค.
- *x (RHS์ ๊ฒฝ์ฐ)
- ๋ณ์์ ๊ฐ์ด ๊ฐ๋ฆฌํค๋ ์ฃผ์์ ๊ฐ์ ๋ฆฌํดํ๋ค.
- *x (LHS์ ๊ฒฝ์ฐ)
- ๋ณ์์ ๊ฐ์ด ๊ฐ๋ฆฌํค๋ ์ฃผ์์ RHS ๊ฐ์ ์ ์ฅํ๋ค.
const ํค์๋
const๊ฐ ๋ถ์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ๋ค๋ฅธ ๊ฐ์ด ํ ๋น ๋ ์ ์๋๋กํ๋ค.(immutable)
int main() {
const int x = 16;
int y = 99;
x = 20; // x์ ์ฃผ์ ๊ฐ์ ๋ ์ด์ ๊ฐ์ ํ ๋นํ ์ ์๋ค.
y = 31;
return 1;
}
const ๊ฐ ๋ถ์ pointers
int main() {
const int x = 16;
int* y = &x;
*y = 10;
return 1;
}
์ฌ๊ธฐ์ y์ ํ์ ์ int* ์ด๋ค. ๊ทธ๋ฆฌ๊ณ y๋ผ๋ ๋ณ์์ x์ ์ฃผ์๋ฅผ ์ ์ฅํ๋ ์ํฉ์ด๋ค.
์ด๋, `int * y = &x` ๋ถ๋ถ์์ ์ปดํ์ผ ์๋ฌ๊ฐ ๋๋ค. ๊ทธ ์ด์ ๋ ์ด๋ฏธ x์ ์ฃผ์๋ freeze ๋ ์ํ์ธ๋ฐ, `int * y = &x`๋ฅผ ํ์ฉํด์ค๋ค๋ฉด ๊ทธ ์ฃผ์๋ฅผ ๋ฐ๊ฟ ์๋ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ฆ, y๊ฐ ์ค์ง์ ์ผ๋ก x์ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๊ธฐ ๋๋ฌธ์ y๋ฅผ ํตํด x์ ์ฃผ์๋ฅผ ๋ฐ๊ฟ ๊ฐ๋ฅ์ฑ์ด ์๊ธด๋ค.
์ปดํ์ผ์๋ฌ๊ฐ ๋์ง ์๋๋ก ํ๊ธฐ ์ํด์๋ `const int* y`๋ก ์ ์ฅํด์ผ ํ๋ค. ์ด๋ y๋ฅผ ๋ฐ๋ผ๊ฐ๋ฉด ๊ฐ์ ๋ฐ๊พธ์ง ๋ชปํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค. ์์ ๋ฐฐ์ด const์ ์ ์๋ฅผ ์๊ฐํด๋ณด์. const๊ฐ ๋ถ์ ๋ณ์๋ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค.
const๊ฐ ๋ถ์ `int* y`์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๊ณ , ์ฌ๊ธฐ์๋ x์ ์ฃผ์๊ฐ ํ ๋น๋๋ค. ์ฆ, x์ ์ฃผ์์ ๊ฐ์ ๋ฐ๊ฟ ์ ์๋ค๋ ๊ฒ๊ณผ ๊ฐ์ ๋งฅ๋ฝ์ด ๋๋ค.
์๋ ์์ ์ฝ๋๋ก ์ด๋ฅผ ํ์ธํ ์ ์๋ค.
int main() {
const int x = 16;
const int* y = &x; // ์ฌ๊ธฐ์๋ ์๋ฌ๊ฐ ๋์ง ์๋๋ค.
*y = 10; // ์ด ๋ถ๋ถ์ y๊ฐ ๊ธฐ๋ฆฌํค๋ ์ฃผ์์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๊ธฐ ๋๋ฌธ์ ์๋ฌ๊ฐ ๋๋ค.
return 1;
}
๋ค๋ฅธ ๊ฒฝ์ฐ๋ฅผ ํ๋ฒ ์ดํด๋ณด์.
int main() {
int x = 16;
int z = 30;
int* const y = &x;
y = &z;
return 1;
}
์ฌ๊ธฐ์ `int* const y`๋ ์๊ธฐ ์์ ์ด ์ผ๋ ค์ ธ ์๋ ๊ฒ์ ๋งํ๋ค.
์์ ๋งํ๋ฏ์ด const๋ ๊ฐ๋ฆฌํค๋ ๋์์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ๊ฐ์ ๋ณ๊ฒฝํ์ง ๋ชปํ๋ ๊ฒ์ด๋ค. y์ ํ์ ์ int*์ด์ง๋ง, y ์์ฒด๋ ๋ฐ๊ฟ ์ ์๋ค.
`int* y`๋ฅผ ํน๋ณํ๊ฒ ์๊ฐํ์ง ๋ง์. ์ด์งํผ ๋๊ฐ์ด ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ ๋น๋๋ ์ฃผ์์ด๋ฉฐ, ๊ทธ ์์ ๋ค์ด์๋ ๊ฐ์ ํ์ ์ด `int*`์ผ ๋ฟ์ด๋ค. ์ฆ, `int* const y`๋ y์ ์ฃผ์์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค๋ ๊ฒ์ด๋ค. ์ด๋ `y = &z`์ ๊ฐ์ด ๊ทธ ์ฃผ์์ ๊ฐ์ ๋ค๋ฅธ ๊ฐ์ ํ ๋นํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํจ์ ์๋ฏธํ๋ค.
๋จ, y๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ์ธ int* y๊ฐ ์ ์ฅํ๊ณ ์๋ ํฌ์ธํฐ์ ์ฃผ์์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค. ์๋ ์์๋ฅผ ํตํด ํ์ธํด ๋ณด์.
int main() {
int x = 16;
int* const y = &x;
x = 20; // OK
*y = 10; // OK
return 1;
}
const ๊ฐ ๋ถ์ class
- ๋ฉค๋ฒ ํจ์์๋ const๊ฐ ๋ถ์ ์ ์๋ค. ๋ค๋ง, ๋ถ์ ๋ถ๋ถ์ด ์ด๋๋์ ๋ฐ๋ผ ๊ทธ ์๋ฏธ๋ ๋ค๋ฅด๋ค.
- return๋๋ ๋ถ๋ถ์ ๋ถ์ ๊ฒฝ์ฐ : return ๋๋ ๊ฐ์ด ๋ถ๋ณ์ด๋ค.
- ํ๋ผ๋ฏธํฐ ํ์ ์ ๋ถ์ ๊ฒฝ์ฐ : ์ธ์์ ๊ฐ์ด ๋ถ๋ณ์ด๋ค.
- ํจ์ ์ด๋ฆ ๋ค์ ๋ถ์ ๊ฒฝ์ฐ : ํจ์์์ผ๋ก ์ ๋ฌ๋๋ object(this)์ ๊ฐ์ด ๋ถ๋ณ์ด๋ค.
class Car {
public:
Car(std::string name) : name_(name) {}
const std::string* name() { return name_; } // ๋ฆฌํด ๋๋ ๋ณ์๊ฐ ๋ถ๋ณ์ด๋ค.
void set_name(const std::string name) { name = name + "hi" } // ์ธ์์ธ name์ ๋ถ๋ณ์ด๋ผ ์๋ฌ
void DoSomething() const { name_ = name_ + "hi"; } // ํจ์๋ก ์ ๋ฌ๋ object๊ฐ ๋ถ๋ณ์ด๊ธฐ ๋๋ฌธ์ name_๋ ๋ถ๋ณ์ด๋ค.(this.name_)
private:
std::string name_;
Door doors[4];
};
int main() {
Car car1("mycar");
std::string* car_name = car1.name(); // ๋ฆฌํด๋๋ name์ด ๋ถ๋ณ์ด๊ธฐ ๋๋ฌธ์ ํ์ฉ๋์ง ์๋๋ค.
// ๊ฐ๋ฅํ๊ฒ ํ๋ ค๋ฉด, const๋ฅผ ๋ถ์ฌ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์ ๊ฐ์ด ๋ณํ์ง ์๋๋ก ํด์ผ ํ๋ค.
return 1;
}
์ ์ฝ๋๋ const๊ฐ ๊ฐ ๊ฒฝ์ฐ์ ๋ฐ๋ผ ์๋๋ ๊ฒฝ์ฐ๋ฅผ ์ฝ๋๋ก ๋ํ๋ด์๋ค. ์กฐ๊ธ ์์ํ ํจ์๋ค์ const๋ ๊ทธ๋ฅ ํจ์ ์์ object์ ๋ฉค๋ฒ ๋ณ์๊ฐ๋ ๋ฐ๊ฟ ์ ์๋ค๋ ๋ป์ด๋ค.
Shallow copy vs. Deep copy
๋ ๋ค copy๋ฅผ ํ๋ ๊ฒ์ ์์ด ์ฐจ์ด๋ ์๋ค. ๋ค๋ง, ๊ฐ์ ์ฃผ์๋ฅผ ๋ฐ๋ผ๋ณด๋ ์ง ๋ค๋ฅธ ์ฃผ์๋ฅผ ๋ฐ๋ผ๋ณด๋ ์ง์ ์ฐจ์ด๋ค. ๋ฌผ๋ก ๋๋ค ํฌ์ธํฐ์ฌ์ผ ํ๋ค.
- Shallow copy(์์ ๋ณต์ฌ)
- ๊ฐ์ ํฌ์ธํฐ ๊ฐ์ ๋ฐ๋ผ๋ณด๋๋ก ํ๋ค.(๊ฐ์ ๊ฐ๋ค.)
- ์ฆ, ๋ฉ๋ชจ๋ฆฌ ์์ฒด๋ฅผ ๋ณต์ฌํ์ง ์๊ณ , ์ฃผ์๋ง ๋ณต์ฌํ๋ค.
- x = y
- Deep copy(๊น์ ๋ณต์ฌ)
- ์์ ํ ๋ค๋ฅธ ํฌ์ธํฐ ๊ฐ์ ๋ฐ๋ผ๋ณด๋๋ก ํ๋ค. (๊ฐ์ ๊ฐ๋ค.)
- ์ฆ, ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ๋ณต์ฌํ์ง ์๊ณ , ๋ฉ๋ชจ๋ฆฌ ์์ฒด๋ฅผ ๋ณต์ฌํ๋ค.
- `x = new char[3]; strcpy(x, y);`
copy constructor์์์ shallow copy
์ฌ์ค ๋ฐ๋ก ์์ฑํ์ง ์์๋ shallow copy๋ ๋ฐ๋ก ์ ์ฉ๋๋ค. ์ด๋ ๊ฐ์ฒด์์ ํ๋กํผํฐ ์ค ํฌ์ธํฐ ๋ฉค๋ฒ๋ค์ ๋ณต์ฌํ ๋, ๋ฉ๋ชจ๋ฆฌ ์์ฒด๋ฅผ ๋ณต์ฌํ๋ ๊ฒ์ด ์๋ ์ฃผ์๋ง์ ๋ณต์ฌํ๋ค. ์ฆ, name_์ด ๊ฐ๋ฆฌํค๋ ๊ณณ์ ๊ฐ์ copyํ๋ ๊ฒ์ด ์๋๋ผ, name_์ด ๊ฐ๋ฆฌํค๋ ๊ณณ๋ง์ copyํ๋ ๊ฒ์ด๋ค.
์ด๋ car1๊ณผ ๋ณต์ฌ๋ ๊ฐ์ฒด car2์ ๋ฉค๋ฒ ๋ณ์ name_์ด ๋์ผํ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ฒ์ด ๋๊ณ , ์ฃผ์์ ๋ ๊ฐ์ ๋ฐ๊พธ๋ฉด ๋ ๋ค ๋์์ ๋ฐ๋๊ฒ ๋๋ค.
class Car {
public:
Car(char* name) {
name_ = new char[sizeof name];
strcpy(name_, name);
}
Car(const Car& car) : name_(car.name_) {} // shallow copy, ๋ณ๋๋ก ์ง์ ํ์ง ์์๋ ์ข๋ค.
...
private:
char* name_;
}
int main() {
Car car1("mycar");
Car car2 = car1;
std::cout << car1.name() << std::endl; // mycar
std::cout << car2.name() << std::endl; // mycar
car1.set_name("yourcar");
std::cout << car1.name() << std::endl; // yourcar
std::cout << car2.name() << std::endl; // yourcar
}
copy constructor์์์ Deep copy
deep copy๋ ๋ฐ๋ก ์๋ก์ด ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ํ ๋นํด ์ฃผ์ด์ผ ํ๋ค. ์ฆ, object๋ฅผ ์์ฑํ ๋, ์๋กญ๊ฒ name์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํด์ฃผ๊ณ ์ ์ฅํด์ผ ํ๋ค.
class Car {
public:
Car(char* name) {
name_ = new char[sizeof name];
strcpy(name_, name);
}
Car(const Car& car) { // deep copy๋ฅผ ์ํ constructor
name_ = new char[sizeof car.name_];
strcpy(name_, car.name_);
}
...
private:
char* name_;
}
int main() {
Car car1("mycar");
Car car2 = car1;
std::cout << car1.name() << std::endl; // mycar
std::cout << car2.name() << std::endl; // mycar
car1.set_name("yourcar");
std::cout << car1.name() << std::endl; // yourcar
std::cout << car2.name() << std::endl; // mycar
}
์์ฑ์์์ ๋ฉค๋ฒ ๋ณ์์ ๊ฐ์ ์ง์ ํด ์ฃผ๊ธฐ ์ํด ์๋กญ๊ฒ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํด์ฃผ๋ ์ฝ๋๋ฅผ ๋ณผ ์ ์๋ค.
Car(const Car& car) { // deep copy๋ฅผ ์ํ constructor
name_ = new char[sizeof car.name_];
strcpy(name_, car.name_);
}
Function calls in C++
function์ ์ธ์๋ฅผ ์ด๋ ํ ๋ฐฉ์์ผ๋ก ์ ๋ฌํด์ฃผ๋ ์ง๋ ํฌ๊ฒ 3๊ฐ์ง ๋ฐฉ์์ผ๋ก ๋๋๋ค.
- Call by values
- ๊ฐ์ copyํ์ฌ ์ ๋ฌํ๋ค.
- Call by pointers
- ์ธ์์ ์ฃผ์๋ฅผ ์ ๋ฌํ๋ค.
- Call by reference
- ์ธ์์ ์ฐธ์กฐ ๊ฐ์ ์ ๋ฌํ๋ค.
Call by values
์ธ์์ ๊ฐ์ ๋ณต์ฌํ์ฌ ๋๊ฒจ์ค๋ค. Caller์ ๊ฐ์ด Callee์ ๋ณํ์ ๋ฐ์๋์ง ์๋๋ค. ์ด๋ ๊ฐ์ด ๋ณต์ฌ๋์๊ธฐ ๋๋ฌธ์ด๋ค.
class Car {
public:
Car(std::string name) : name_(name) { }
Car(const Car& car) : name_(car.name_ {}
void set_name(std::string name) { name_ = name; }
std::string name() { return name_; }
private:
std::string name_;
};
void ChangeCarName(Car car2, std::string name) {
car2.set_name(name);
}
int main() {
Car car1("mycar");
std::cout << car1.name() << std::endl; // mycar
ChangeCarName(car1, "yourcar");
std::cout << car1.name() << std::endl; // mycar
return 1;
}
์ ChangeCarName์์ car1 ์์ฒด๊ฐ ๋ณต์ฌ๋์ด ๋์ด๊ฐ๋ค. ์ด๋ ๊ฒ ๊ฐ์ฒด๊ฐ ํจ์์ ๋งค๊ฐ๋ณ์๋ก ๋์ด๊ฐ๋ Call by Value๋ shallow copy๊ฐ ์งํ๋๋ค.
shallow copy๊ฐ ์งํ๋๋ฉด, ํด๋์ค ์์ ๋ฉค๋ฒ๋ค์ด ๋ณต์ฌ๊ฐ ๋ ๊ฒ์ด๋ค. ์ฌ๊ธฐ์ ํ ๋ฒ ๋ shalllow copy์ deep copy๋ฅผ ์ง๊ณ ๋์ด๊ฐ์. shallow copy๋ ํฌ์ธํฐ ๋ฉค๋ฒ๊ฐ ์์ ๋, ๋ฉ๋ชจ๋ฆฌ ์์ฒด๋ฅผ ๋ณต์ฌํ์ง ์๊ณ ๊ทธ ์ฃผ์๋ง ๋ณต์ฌํ๋ ๊ฒ์ด๋ค. deep copy๋ ํฌ์ธํฐ ๋ฉค๋ฒ๊ฐ ์์ ๋, ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ ๋์ ๋ฉ๋ชจ๋ฆฌ ์์ฒด๋ฅผ ๋ณต์ฌํ๋ค.
๊ทธ๋ฌ๋๊น Car์ ๋ฉค๋ฒ ์ค name_์ ํฌ์ธํฐ ๋ณ์๊ฐ ์๋๋ฏ๋ก, ๊ตณ์ด shallow copy๋ deep copy๋ฅผ ์ ๊ฒฝ ์ธ ํ์๊ฐ ์๋ค. ๊ทธ ๊ฐ๋ง์ด ๋ณต์ฌ๋๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค.(๊ทธ๋ฅ copy)
์ฆ, car2์ ๋ณต์ฌ๋๋ ์๋ก์ด name_์ ๊ธฐ์กด์ car1์ name_๊ณผ ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ๊ฐ์ ๊ฐ๋ง์ ๊ฐ์ง ์ ์๊ณ , car1์์ ์ ๊ทผํ๋๋ผ๋ mycar๋ง์ด ์ถ๋ ฅ๋๋ ๊ฒ์ด๋ค.
Call by Pointer
Call by Pointer๋ ์ธ์์ ์ฃผ์๋ฅผ ๋๊ธด๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ Callee์ ๋ณํ๊ฐ Caller์๊ฒ ๋ฐ์๋๋ค. ๊ฐ์ ์ฃผ์๊ฐ ๊ฐ๊ธฐ ๋๋ฌธ์ด๋ค. ๋ํ NULL pointer ๋ํ ๊ฐ์ ์ธ์๋ก์จ ์ ๋ฌ๋ ์ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๊ฒ์ฆํ๋ ์ฝ๋ ๋ํ ํ์ํ๋ค.
์ผ๋ฐ์ ์ผ๋ก Call by Value๋ณด๋ค ๋น ๋ฅด๊ธฐ ๋๋ฌธ์ ๋ง์ด ์ฌ์ฉํ๋ค.
void Add3(int * y) {
if (y != NULL)
*y += 3;
}
int main() {
int x = 1;
std::cout << x << std::endl; // 1
Add3(&x); // ์ฃผ์์ ๊ฐ์ ์ ๋ฌํ๋ค.
std::cout << x << std::endl; // 4
}
Call by Reference
Call by Pointer์ ํท๊ฐ๋ฆด ์ ์๋ค. ์ฐจ์ด์ ์ Call by Pointer๋ ํฌ์ธํฐ ๊ฐ(์ฆ, ์ฃผ์ ๊ฐ)์ ๋๊ฒจ ์ฃผ์๋ก์จ ๊ฐ์ ๋ณ๊ฒฝํ๋ ๊ฒ์ด๋ค. Call by Reference๋ ์ข๋ณ์ ๊ฐ(์ฆ, lvalue)์ ๋๊ฒจ ํ์ฌ ์ ๋ฌํ๊ณ ์ ํ๋ ๊ฐ์ ์ฐธ์กฐ๋ฅผ ๋๊ธด๋ค. ๊ฐ๋จํ๊ฒ ์๊ฐํด๋ณด์๋ฉด ๊ฐ์ ์ฐธ์กฐ ๊ทธ ์์ฒด๋ฅผ ๋๊ธฐ๋ ๊ฒ์ด๋ค.
Call by Pointer์ ๋ง์ฐฌ๊ฐ์ง๋ก callee์ ๋ณํ๊ฐ caller์ ๋ฐ์๋๋ฉฐ, Call by Value ๋ณด๋ค ๋น ๋ฅด๋ค. ๋ค๋ง, NULL์ ํ์ฉ๋์ง ์๋๋ค.
void Add3(int& y) {
y += 3;
}
int main() {
int x = 1;
std::cout << x << std::endl; // 1
Add3(x);
std::cout << x << std::endl; // 4
return 1;
}
return ๊ฐ์ด Copy ๋๋ ๊ฒฝ์ฐ
์๋ฌด ๊ฒ๋ ์ฐ์ง ์์ ๊ฒฝ์ฐ, ํจ์์์ ๋ฆฌํด ๊ฐ์ ๋ณต์ฌ๋์ด ์ ๋ฌ๋๋ค. ๊ฐ ๊ทธ ์์ฒด๊ฐ copy๋์ด ๋ฆฌํด๋๋ค๊ณ ์๊ฐํ์. ๊ทธ๋์ ๋ฆฌํด๋ ๊ฐ์ ๋ฐ๊พธ์ด๋, ํด๋น object ๋ด์์์ ๊ฐ์ ๋ณํ ์ ์๋ค.
class Car {
public:
Car(std::string name) : name_(name) { }
void set_name(std::string name) { name_ = name; }
std::string name() { return name_; }
private:
std::string name_;
}
int main() {
Car car1("mycar");
std::string car_nmae = car1.name();
car_name += " hi";
std::cout << car1.name() << std::endl; // mycar
return 1;
}
return ๊ฐ์ด Address์ธ ๊ฒฝ์ฐ
ํฌ์ธํฐ๋ฅผ ๋ฆฌํดํ๋ ๊ฒฝ์ฐ์ด๋ค. ์ด๋, ์ฃผ์๋ฅผ ๋๊ฒจ์ฃผ๊ธฐ ๋๋ฌธ์ ์๋ณธ์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ์ ์๋ค. ๋ํ ํฌ์ธํฐ์ด๊ธฐ ๋๋ฌธ์ NULL๋ ๋ฆฌํด๋ ์ ์๋ค.
์ผ๋ฐ์ ์ผ๋ก Value๋ฅผ ๋ฆฌํดํ๋ ๊ฒ ๋ณด๋ค ๋น ๋ฅด๋ค. (๊ฐ์ copyํ๋ฉด, ๋ฉ๋ชจ๋ฆฌ๋ ๋ ํ ๋นํด์ผ ํ๊ธฐ ๋๋ฌธ)
class Car {
public:
Car(std::string name) : name_(name) { }
void set_name(std::string name) { name_ = name; }
std::string* name() { return &name_; } // address๋ฅผ ๋ฆฌํดํ๋ค.
private:
std::string name_;
}
int main() {
Car car1("mycar");
std::string* car_nmae = car1.name();
if (car_name != NULL) // NULL ์ฒดํฌ๋ฅผ ๊ผญ ํด์ฃผ์.
*car_name += " hi";
std::cout << car1.name() << std::endl; // mycar hi
return 1;
}
return ๊ฐ์ด Reference์ธ ๊ฒฝ์ฐ
๊ฐ์ ์ฐธ์กฐ๋ฅผ ๋ฆฌํดํ ๋์ด๋ค. (member field)
์๋ณธ์ ๊ฐ์ด ๋ณ๊ฒฝ ๋ ์ ์์ผ๋ฉฐ, NULL ๊ฐ์ ํ์ฉ๋์ง ์๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก Value๋ฅผ ๋ฆฌํดํ๋ ๊ฒ ๋ณด๋ค ๋น ๋ฅด๋ค.
class Car {
public:
Car(std::string name) : name_(name) { }
void set_name(std::string name) { name_ = name; }
std::string& name() { return name_; } // reference๋ฅผ ๋ฆฌํดํ๋ค.
private:
std::string name_;
}
int main() {
Car car1("mycar");
std::string& car_nmae = car1.name();
car_name += " hi";
std::cout << car1.name() << std::endl; // mycar hi
return 1;
}
ํจ์์์ ์ง์ญ ๋ณ์๋ฅผ ๋ฆฌํดํ ๋, Address๋ Reference๋ฅผ ์ฌ์ฉํ์ง ๋ง์.
GetCarA์ GetCarR์์ tmp_car๋ ์ง์ญ ๋ณ์์ด๋ค. ์ฆ, ํด๋น ํจ์ ์ค์ฝํ๋ฅผ ๋ฒ์ด๋๋ฉด ํด๋น ๊ฐ์ฒด์ ์ฃผ์๊ฐ ํ๊ธฐ๋๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํ ์ ์๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ pointer๋, reference๋ก ๋ฐํํ๋ฉด error๊ฐ ๋๋ ๊ฒ์ด๋ค.
๋ฐ๋ฉด, GetCarV์์๋ Car("value")๋ผ๋ ๊ฐ์ฒด๊ฐ ์์ฑ๋์ด ๋ณต์ฌ๋์ด ๋ฆฌํด๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ํจ์ ์ค์ฝํ๋ฅผ ๋ฒ์ด๋๋, ์ฌ์ฉํ ์ ์๋ค.
์ด ์์ ๊ฐ์ฒด๋ `Car car_value`์์ copy constructor๊ฐ ๋์๋์ด ๋ฐํ๋๊ธฐ ๋๋ฌธ์ name์ ํธ์ถํ ์ ์๋ค๋ ๊ฒ์ด๋ค.
Car GetCarV() {
return Car("value");
}
Car* GetCarA() {
Car tmp_car("address");
return &tmp_car;
}
Car& GetCarR() {
Car tmp_car("reference");
return tmp_car;
}
int main() {
Car car_value = GetCarV();
std::cout << car_value.name() << std::endl; // OK
Car* car_address = GetCarA();
std::cout << car_address.name() << std::endl; // ERROR
Car& car_reference = GetCarR();
std::cout << car_reference.name() << std::endl; // ERROR
return 1;
}
Function Overloading
๋๊ฐ์ ์ด๋ฆ์ ํจ์๋ฅผ ์ฌ๋ฌ ๋ฒ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ ๊ฒ์ด๋ค. C++, Java๋ ์ง์ํ์ง๋ง C๋ ์ง์ํ์ง ์๋ ํน์ง์ด ์๋ค.
- Function descriptor : ๋ฆฌํด ํ์ , ํจ์ ์ด๋ฆ, ํ๋ผ๋ฏธํฐ ํ์ ์ด ์ผ์นํ๋ ๊ฒ
- Function signature : ํจ์ ์ด๋ฆ, ํ๋ผ๋ฏธํฐ ํ์ ์ด ์ผ์นํ๋ ๊ฒ
์ด๋ฌํ Function Overloading์ Signature๊ฐ ๋ฌ๋ผ์ผ ์ ์ํ ์ ์๋ค.
int foo(int x);
int foo(int x, int y);
int foo(char x);
void foo(double x);
void foo(int x); // Error
๋ค์๋งํด ํ๋ผ๋ฏธํฐ์ ๊ฐฏ์๋ ํ์ ์ด ๋ค๋ฅด๋ฉด ์ฌ์ ์ ํ ์ ์๋ค. ๊ธฐ์ตํ ๋งํ ์ ์ ์ด๋ฌํ Function Overloading์ ๊ฐ๋ฅํ๊ฒ ํ๋ ๊ฒ์ ์ปดํ์ผ๋ฌ(Compiler)๋ผ๋ ๊ฒ์ด๋ค.
์ด๋ฅผ ์ฐ๋ฆฌ๋ static dispatch๋ผ๊ณ ํ๋ค. ๊ฒฐ์ ํด ์ฃผ๋ ๊ฒ ์์ฒด๋ dispatch๋ผ๊ณ ํ๊ณ , static์ ์ปดํ์ผ ๊ณผ์ ์ ์๋ฏธํ๋ค.
(๋ฐ๋๋ก runtime ์ ๊ฒฐ์ ๋๋ ๊ฒ์ dynamic dispatch๋ผ๊ณ ํ๋ค.)
Overloading resolution rules
Function Overloading์ ๊ณผ์ ์ ์๋์ ๊ฐ์ด ๋์ํ๋ค.
1. viable function์ ์์งํ๋ค.
- ํจ์ ์ด๋ฆ์ด ๊ฐ๊ณ , ํ๋ผ๋ฏธํฐ ๊ฐฏ์๊ฐ ๊ฐ์ ๊ฒ๋ค์ ์์งํ ๊ฒ์ ์๋ฏธํ๋ค.
- ๋ง์ฝ ์ฐพ์๋๋ฐ ํ๋๋ผ๋ฉด ๊ฑฐ๊ธฐ์ ๋๋ธ๋ค.
2. ์ฌ๋ฌ ๊ฐ๋ผ๋ฉด ๊ทธ ์ค์์ best matched ํ๋๋ฅผ ๋ฝ๋๋ค.
- Exact Match : ์ธ์์ ํ์ ๊ณผ ํ๋ผ๋ฏธํฐ ํ์ ์ด ์ ํํ ์ผ์นํ๋ ๊ฒ
- Promotion : ํ์ฅ๋ ์ ์๋ ๊ฒ(4byte๋ฅผ ๋๊ฒผ๋๋ฐ, 8byte๋ก ๋ฐ์ ์ ์๋ ๊ฒ์ ๋ฝ๋๋ค.). ๋ฐ์ดํธ๊ฐ ๊ฐ๋ค๋ฉด promotion์ด ์๋๋ค. ์ด๋ ์น๊ฒฉ์ (char, short -> int), (float -> double)๋ง ๊ฐ๋ฅํ๋ค.
- Standard type conversion : ํ์ ์ด ๋ณํ๋ ์ ์๋ ๊ฒ(int > char). ์์ค์ด ๋ฐ์ํ ์๋ ์๋ค. ์ฆ, ์์ ๋ณด๋ค byte๊ฐ ์์ ํ์ ์ผ๋ก ๋ณํ์ด ๊ฐ๋ฅํ๋ค. ์ฌ์ค ์ ๋ถ ๊ฐ๋ฅํ ๊ฒ ๊ฐ์๋ฐ, ์์ค์ด ๋ฐ์ํ ๊ฒฝ์ฐ๋ง ๊ธฐํ ๋น์ฉ์ ๋ฐ์ง๋ค.
- Implicit or User-defined type Conversion
- Error
best matched๋ ์์ ์์๋ฅผ ๋ฐ๋ฅธ๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ํจ์ ์ด๋ฆ๊ณผ ํ๋ผ๋ฏธํฐ ๊ฐฏ์๊ฐ ๊ฐ์ ์ง ํ์ธํ๋ค. ์ดํ, ํ๋ผ๋ฏธํฐ ํ์ ์ ์ผ์น ์ฌ๋ถ์ ํ์ฅ ์ฌ๋ถ, ํ์ ๋ณํ ์ฌ๋ถ ๋ฑ์ ํ์ธํ๋ค.
void foo(int x) { std::cout << "foo(int x)" << std::end; }
void foo(int x, float y) { std::cout << "foo(int x, float y)" << std::endl; }
void foo(float x, float y) { std::cout << "foo(float x, float y)" << std::endl; }
void foo(float x) { std::cout << "foo(float x)" << std::endl; }
int main() {
foo(3); // Exact match
foo('a'); // Promotion
foo(1, 2); // conversion
foo(1.3f, 2.4); // conversion
foo(1.3) // ๋๊ฐ์ง ํจ์๋ก ๋ฐ๊ฟ ์ ์๊ธฐ ๋๋ฌธ์ ์๋ฌ
}
์ ์์๋ฅผ ํ๋ ํ๋ ์ดํด๋ณด๋๋ก ํ์.
- foo(3) :
- ๋์ผํ ํ๋ผ๋ฏธํฐ์ ํ์ ์ด ์กด์ฌํ๋ค. ๋ฐ๋ผ์ Exact Match๋ก ์ฒ๋ฆฌํด์ค๋ค.
- foo('a') :
- ๋์ผํ ํ๋ผ๋ฏธํฐ๋ ์์ผ๋ฏ๋ก, promotion์ผ๋ก ๋์ด๊ฐ๋ค. 'a'๋ char์ด๋ฏ๋ก 1byte์ด๊ณ , foo(int x)๊ฐ ๊ฐ๋ฅํ๋ค.
- foo(1, 2) :
- ๋์ผํ ํ๋ผ๋ฏธํฐ๋ ์์ผ๋ฉฐ, void foo(int x, float y)์ void foo(float x, float y)๋ ์น๊ฒฉ์ด ๋ถ๊ฐ๋ฅํ๋ฏ๋ก ๋์ด๊ฐ๋ค.
- conversion ๋จ๊ณ์์๋ ์ฌ๋ฌ๊ฐ๊ฐ ๋์ค๋๋ผ๋ ๊ธฐํ๋น์ฉ์ด ์ ์ ํจ์๋ฅผ ์ ํํ๋ค. ๋ง์ฝ ์ด ๊ธฐํ ๋น์ฉ ๋ง์ ๊ฐ๋ค๋ฉด, ์๋ฌ์ด๋ค.
- ์ฌ๊ธฐ์๋ foo(int x, float y)๊ฐ ๊ธฐํ ๋น์ฉ์ด ์ ์ผ๋ฏ๋ก ์ด๋ฅผ ์ ํํ๋ค.
- foo(1.3f, 2.4) :
- promotion์ผ๋ก ๊ฐ๋ฅํ ๊ฒ์ด ์๋ค. byte๊ฐ ํฐ ํ์ ์ผ๋ก ๋ฐ๋ ๊ฒ์ด ์๊ธฐ ๋๋ฌธ์ conversion์ผ๋ก ๋์ด๊ฐ๋ค.
- conversion ์ foo(int x, float y)์ foo(float x, float y)๊ฐ ์ ํ๋ ์ ์๋ค. ์ด๋ ๊ธฐํ ๋น์ฉ์ด ์ ์ foo(float x, float y)๋ฅผ ์ ํํ๋ค.
- foo(1.3)
- ์์ค์ด ๋ฌด์กฐ๊ฑด ๋ฐ์ํ๋ฏ๋ก conversion์ผ๋ก ๋์ด๊ฐ๋ค.
- conversion ์์๋ ๊ธฐํ ๋น์ฉ์ด ์์ ๊ฒ์ ํํ๋ค. ์ด๋ 1.3์ double์ด๋ฏ๋ก 8byte์ด๊ณ , int๋ 4 byte, float๋ 4byte์ด๋ค. ์ฆ, ๋์ผํ ๊ธฐํ๋น์ฉ์ด ๋ฐ์ํ๋ฏ๋ก, ์ด๋ ์๋ฌ์ด๋ค.
promotion vs. conversion
promotion์ ๋ฐ์ดํธ๊ฐ ์์ ๋ณด๋ค ํฐ์ง๋ฅผ ํ์ธํ๋ค. ๊ฐ์ ๊ฒ์ ์น๊ธ๋์ง ์๋๋ค. ์ด๋ ์ ์ ์น๊ฒฉ, ์ค์ ์น๊ฒฉ ๊ธฐ์ค์ ๋ง์์ผ ํ๋ค. ์ฝ์คํธ๊ฐ ๊ฐ์ผ๋ฉด ๋์ด๊ฐ๋ค.
conversion์ ๋ฐ์ดํธ๊ฐ ์์ ๊ณผ ๊ฐ๊ฑฐ๋ ์์ ๊ฒ์ผ๋ก ๋ณํ๋๋ค. ๋ฐ๋ผ์ ์์ค์ด ๋ฐ์ํ ์๋ ์๋ค. ๊ฐ์ ์ฝ์คํธ๊ฐ ์์ผ๋ฉด ์๋ฌ๊ฐ ๋๋ค.(์ฝ์คํธ๋ ๊ฐ ์ธ์๋ง๋ค ํ๋๋ก ์น๋ค.)
๋ค์ด๋๋ฏน ๋ฉ๋ชจ๋ฆฌ ํ ๋น๊ณผ ํด์
Stack๊ณผ Call Stack์ ๋ํด ๊ฐ๋จํ๊ฒ ์ง๊ณ ๋์ด๊ฐ์.
Stack์ ๋จผ์ ๋ค์ด์จ ๋ฐ์ดํฐ๊ฐ ์ ์ผ ๋ง์ง๋ง์ผ๋ก ๋๊ฐ๋ ์๋ฃ๊ตฌ์กฐ๋ก ๊ต์ฅํ ๋ง์ ๊ณณ์์ ์ฌ์ฉ๋๋ค. Programming Languege์์๋ ์ด๋ ๋ง์ฐฌ๊ฐ์ง์ธ๋ฐ, Call Stack์ด ๊ทธ ์์ด๋ค.
Call Stack์ ๋ฐํ์ ์์ ๋์ํ๋ ํจ์๋ค์ ํธ์ถ์ Stack ์๋ฃ ๊ตฌ์กฐ์ ์ ๋ชฉ์ํจ ๊ฒ์ด๋ค.
stack์์ ๊ฐ ํจ์๋ค์ local data๋ฅผ ์ ์ฅํ๋ค. ์ด ํจ์๋ค ์์์ ๋ค๋ฅธ ํจ์๋ฅผ ํธ์ถ(Call)ํ๊ฒ ๋๋ฉด, ์ ์ ์์ด๋ ๊ตฌ์กฐ๊ฐ ๋๊ณ , ํธ์ถํ ํจ์๊ฐ ์ข ๋ฃํ๋ฉด, pop๋๋ ๊ตฌ์กฐ๊ฐ ๋๋ค.
์ปดํ์ผ๋ฌ๋ ์ด๋ ๊ฒ ํธ์ถ๋ ํจ์๊ฐ ์ผ๋ง๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๋ ์ง ์๊ณ ์๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ํจ์๊ฐ ํธ์ถ๋๋ฉด, Stack์ ์ ์ ํ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ ๋นํ์ฌ ๋ฐฐ์นํ ์ ์๋ ๊ฒ์ด๋ค. ์ดํ, ํธ์ถ์ด ๋๋๋ฉด, ๋ฉ๋ชจ๋ฆฌ ์์ ๋ณ์๋ค์ ํ ๋น์ด ํด์ ๋๋ค.
Heap memory allocation
๋ฉ๋ชจ๋ฆฌ๋ ํ ์์ญ ์์์ ํ ๋น๋๋ค. ์ด๋ ๊ฒ ํ ๋นํ๋ ๊ณผ์ ์ dynamic memory allocation์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค. ์ด ๋ฉ๋ชจ๋ฆฌ์ Size๋ ๋ฐํ์ ์์ ๊ณ์ฐ๋์ด ํ ๋น๋๋ค.
์ด๋ฌํ dynamic memory allocation์ ๋ช ์์ ์ผ๋ก ํ ๋น/ํด์ ๊ณผ์ ์ ๋ํ๋ด ์ฃผ์ด์ผ ํ๋ค. ๋ํ ์ด ๊ณผ์ ์์ ๋ฐ์ํ ์ ์๋ ๋ฉ๋ชจ๋ฆฌ ๋์๋, Dangling pointer ์๋ฌ๋ฅผ ์กฐ์ฌํด์ผ ํ๋ค.
void foo() {
int* x = (int*) malloc(sizeof(int));
int* arr = (int*) malloc(sizeof(int)*4);
Node* n = new Node;
free(x);
free(arr);
delete n;
}
new ์ฐ์ฐ์๋ฅผ ํตํ Dynamic allocation
- C++์์ new ํค์๋๋ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ์์ ์ฌ์ฉ๋๋ค.
- ์ผ๋ฐ์ ์ผ๋ก malloc๊ณผ ๋๊ฐ์ด ๋์ํ๋ค.
- ๋ค๋ฅธ ์ ์ new ์ฐ์ฐ์๋ ๋ฉ๋ชจ๋ฆฌ(heap) ์์ญ์ ๊ณต๊ฐ์ ํ ๋นํ๊ณ ๊ฐ์ฒด๋ฅผ ์์ฑํ ํ, ๊ทธ ์ฃผ์๋ฅผ ๋ฐํํ๋ค. ๋ํ constructor๋ฅผ ์ ๋ฐ์ํจ๋ค.
- delete n์ ํตํด์ destructor๋ฅผ ํธ์ถํ ์ ์๋ค.
- destructor๊ฐ ํธ์ถ๋๊ธฐ ์ด์ ์ ๋ค๋ฅธ ๋ช ๋ น์ ๋ด๋ ค ๋์์ ์ํํ ์๋ ์๋ค.
- delete๋ destructor๋ฅผ ํธ์ถํ๋ค.
๋ฉ๋ชจ๋ฆฌ ๋์(Memory Leak)
๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํด ๋๊ณ , ํด์ ํ์ง ์์์ ๋ ์๊ธด๋ค.
void bax() {
Node* n = new Node(3);
// ๋ฉ๋ชจ๋ฆฌ ํด์ ์์ด ๋ฆฌํด
return;
}
์๋ ์์ ์ ๊ฒฝ์ฐ, n์ ์ฌ๋ฌ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋ค๊ฐ ๋ง์ง๋ง์ ํ ๋น๋ ์ฃผ์๋ง์ ๊ฐ๋ฆฌํค๊ธฐ ๋๋ฌธ์ ์ ๋ถ ๋ฉ๋ชจ๋ฆฌ ํด์ ๋ ์ ์๋ค.
void bar() {
Node* n;
for(int i=0; i<100; ++i) {
n = new Node(i);
}
delete n;
}
Dangling pointer
์ด๋ฏธ ํ ๋น ํด์ ๋ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํ๋ ค๊ณ ํ ๋ ๋ฐ์ํ๋ ์๋ฌ์ด๋ค.
void foo() {
Node* n = new Node(3);
delete n;
n-> ...
}
n์ ๊ฐ๋ฆฌํค๋ ๊ณต๊ฐ์ด ์ด๋ฏธ ํด์ ๋์๋๋ฐ, ์ ๊ทผํ๋ ค๊ณ ํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ค. ์ด๋ก์ธํด ๋ฐ์ํ ์ ์๋ ๋ฌธ์ ๋ก๋ Segfault, Security vulnerability, Undefined behavior๊ฐ ์๋ค.
Qualifiers and Keywords
Static ํค์๋
`static` ํค์๋๊ฐ ๋ถ๊ฒ ๋๋ฉด, ํ๋ก๊ทธ๋จ์ ์๋ช ๊ธฐ๊ฐ๋์ ํ ๋น๋๋ค. ์ฆ, ํ๋ก๊ทธ๋จ์ด ์์ํ ๋๋ถํฐ ํ ๋น์ด ๋๋ฉฐ ํ๋ก๊ทธ๋จ์ด ์ข ๋ฃ๋ ๋ ํ ๋น ํด์ ๋๋ค.
void foo() {
static int count = 0;
std::cout << count++ << std::endl;
}
int main() {
for(int i=0; i<10; ++i) {
foo();
}
return 1;
}
๊ฐ์ฒด์์์ Static ํค์๋
๋ง์ฐฌ๊ฐ์ง๋ก ๊ฐ์ฒด์์๋ static ํค์๋๊ฐ ๋ถ์ ์ ์๋ค. ์ด object๋ ํ๋ก๊ทธ๋จ์ด ์์๋ ๋ ํ ๋น ๋๊ณ , ๋๋ ๋ ํด์ ๋๋ค.
class Node {
public:
Node(int value) : value_(value) {
std::cout << "Object Creation" << std::endl;
}
~Node() {
std::cout << "Object Deletion" << std::endl;
}
}
void foo() {
static Node n(3);
}
int main() {
std::cout << "Start main" << std::endl;
foo();
foo();
std::cout << "End main" << std::endl;
return 1;
}
Static ๋ฉค๋ฒ ํ๋
static์ด ๋ถ์ ๋ฉค๋ฒ ํ๋๋ Class๋ก ๋ง๋ค์ด์ง ๋ชจ๋ Object์ ๋ํด ๊ฐ์ ๊ณต์ ํ๋ค. ๊ทธ๋์, object๋ฅผ ํตํด static ๋ฉค๋ฒ ํ๋๋ฅผ ํธ์ถํ๋ , Class๋ฅผ ํตํด ํธ์ถํ๋ ๊ฐ์ด ๊ณต์ ๋๊ธฐ ๋๋ฌธ์ ๋์ผํ๋ค.
class Node {
public:
Node(int value) : value_(value) {}
const static int kNodeVersion = 7;
private:
int value_;
};
int main() {
Node n1(1);
Node n2(2);
std::cout << Node::kNodeVersion << std::endl;
std::cout << n1.kNodeVersion << std::endl;
}
Static ๋ฉค๋ฒ ํจ์
๋ฉค๋ฒ ํจ์์ static์ด ๋ถ์ผ๋ฉด, class ๋ด๋ถ์ ๋ฉค๋ฒ ๋ณ์ ์ค, static์ด ๋ถ์ ๋ฉค๋ฒ ๋ณ์๋ฐ์ ๊ฐ์ ธ์ค์ง ๋ชปํ๋ค. ์ด๋ ๋ฉค๋ฒ ๋ณ์์ this ๋ณ์๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.
class Node {
public:
Node(int value) : value_(value) {}
static int GetVersion() {
value_ = 3; // ๋ถ๊ฐ๋ฅ
int x= value_; // ๋ถ๊ฐ๋ฅ
this -> kNodeVersion; // ๋ถ๊ฐ๋ฅ
return kNodeVersion;
}
private:
int value_;
const static int kNodeVersion = 7;
};
์ฑ๊ธํค ๋์์ธ ํจํด
์ค์ง ๋จ ํ๋ฒ์ Object๋ฅผ ์์ฑํ๊ณ ์ถ์ ๋ ์ฑ๊ธํค ๋์์ธ ํจํด์ ์ฌ์ฉํ๋ค.
ํด๋น ๊ฐ์ฒด์ ์ ๊ทผํ๊ณ ์ถ์ ๋๋ class ๋ด๋ถ ๋ฉ์๋๋ฅผ ํตํด ์ ๊ทผํ์ฌ์ผ ํ๋ฉฐ, ์๋กญ๊ฒ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ค.
๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋ ์ ์๋ค๋ ์ ์์ ์์๋ฅผ ๋ ์ ์๋ค.
class NodeUtil {
public:
static NodeUtil* GetInstance() {
if (instance_ == NULL) {
instance_ = new NodeUtil;
}
return instance_;
}
private:
NodeUtil() {}
static NodeUtil* instance_;
}
NodeUtil* NodeUtil::instance_ = NULL;
int main() {
// ์ค์ง ํ๋์ ์ธ์คํด์ค๋ง ์์ฑ๋๋ค.
NodeUtil* util1 = NodeUtil::GetInstance();
NodeUtil* util2 = NodeUtil::GetInstance();
NodeUtil* util3 = NodeUtil::GetInstance();
// ์ด์ธ์ ๋ฐฉ๋ฒ์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ ์๋ ์๋ค.
NodeUtil util4;
return 1;
}
์ค์ํ๊ฒ ๊ธฐ์ตํด์ผ ํ ๊ฒ์ ๋ฐ๋์ ์ด๊ธฐํ ์ฝ๋๋ฅผ ์์ฑํด ์ฃผ์ด์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
`Node* NodeUtil::instance_ = NULL;`๋ผ๋ ์ฝ๋๋ฅผ Class ๋ฐ์์ ์จ๋ฃ์ด ์ฃผ์ด์ผ ํ๋ค.
Mutable ๋ฉค๋ฒ ํ๋
์ด์ ์ const์ ๋ํ์ฌ ๋ ์ฌ๋ ค๋ณด์. ํจ์ ์ด๋ฆ ๋ค์ const๊ฐ ๋ถ์ ๊ฒ์ ๊ทธ ํจ์ body ๋ด๋ถ์์ ํ๋ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์์๋ค. ์ด๋ ํจ์ ๋ด๋ถ์ this๊ฐ const ํฌ์ธํฐ๊ฐ ๋๊ธฐ ๋๋ฌธ์ด๋ค.
ํ์ง๋ง, ์ผ๋ถ ํ๋ ๊ฐ์ ๋ณ๊ฒฝํ๊ณ ์ถ์ ๊ฒฝ์ฐ `mutable`์ด๋ผ๋ ๊ฒ์ ๋ฉค๋ฒ ํ๋ ์์ ๋ถ์ด๋ฉด ๋ฐ๊ฟ ์ ์๋ค.
class Node {
public:
Node(int value) : value_(value), mutable_count(0), normal_count(0) {}
int value() const {
mutable_count_++; // mutable ๋ฉค๋ฒ ํ๋์ด๊ธฐ์ ๊ฐ๋ฅํ๋ค.
normal_count_++; // ๋ถ๊ฐ๋ฅํ๋ค.
return value_;
}
private:
int value_;
mutable int mutable_count_; // mutable ๋ฉค๋ฒ ํ๋
int normal_count_;
}
Operator Overloading
Operator overloading
Operator ์ฐ์ฐ์ ์์ด ์ฌ์ฉ์๊ฐ ์ง์ ์ ์ํ ์ ์๋ ๊ฒ์ ๋งํ๋ค. ๊ฐ๋จํ๊ฒ ๋งํด ๊ฐ์ฒด์ ๊ฐ์ฒด๋ฅผ ๋ง์ ํ์ง๋ ๋ชปํ์ง๋ง, ๊ทธ ๋ง์ ์ฐ์ฐ ๊ณผ์ ์์ ๊ฐ ๊ฐ์ฒด์ ๋ฉค๋ฒ ๋ณ์์ ๋ง์ ์ผ๋ก ๋ฐ๊พธ๋ ๋ฑ์ ๋์์ ์ ์ํ ์ ์๋ค๋ ๊ฒ์ด๋ค.
์ด๋ฌํ ๊ธฐ๋ฅ์ด ๊ฐ๋ฅํ operator๋ ์๋์ ๊ฐ๋ค.
Operator overloading์ ๋ ๊ฐ์ง ํ์
1. ๋ฉค๋ฒ ํจ์๋ก์จ์ Operator overloading
- ์ฒซ ๋ฒ์งธ operand๋ *this๊ฐ ๋๊ณ , ๋ค๋ฅธ ๊ฒ๋ค์ ํ๋ผ๋ฏธํฐ๊ฐ ๋๋ค.(์ฆ, ๋ ๊ฐ์ฒด n1, n2์ ๋ํ์ฌ n1 + n2์ด๋ฉด, n1์ด *this)
- ์ฒซ ๋ฒ์งธ operand๋ ๋ฐ๋์ ์ฌ์ฉ์ ์ ์ ํ์ ์ ๊ฐ์ฒด์ด์ด์ผ ํ๋ค.
- overloaded operator๋ private ๋ฉค๋ฒ ๋ณ์ ํ๋์ ์ ๊ทผํ ์ ์๋ค.
2. ๋ฉค๋ฒ ํจ์๊ฐ ์๋ Operator overloading
- All operands๋ ํ๋ผ๋ฏธํฐ๋ก ์ทจ๊ธ๋๋ค.
- ์ฒซ ๋ฒ์งธ operand๊ฐ ๊ตณ์ด ์ฌ์ฉ์ ์ ์ ํ์ ์ ๊ฐ์ฒด๊ฐ ๋ ํ์๋ ์๋ค.
- overloaded operator๋ private ๋ฉค๋ฒ ๋ณ์ ํ๋์ ์ ๊ทผํ ์ ์๋ค.
1๋ฒ์ ๊ดํ ์์ ์ฝ๋๋ ์๋์ ๊ฐ๋ค.
class Node {
public:
Node(int value) : value_(value) {}
Node& operator+(Node& node) { // + operator overloading, *this๋ n1์ด๋ค. ์ธ์๋ n2์ด๋ค.
value_ += node.value_;
return *this;
}
operator int() { // ํ์
๋ณํ์ ๊ดํ operator overloading, ๋ฆฌํด ํ์
์ ์์ผ๋ ๋ฆฌํดํ๋ค.
return value_;
}
};
int main() {
Node n1(3);
Node n2(4);
std::cout << (int)(n1 + n2) << std::endl;
return 1;
}
๋ค์์ 2๋ฒ์ ๊ดํ ์์ ์ฝ๋์ด๋ค.
class Node {
public:
Node(int value) : value_(value) {}
int value() const { return value_; }
private:
int value_;
}
int operator*(int x, const Node& n) {
return x - n.value();
}
double operator*(double x, const Node& n) {
return x * n.value();
}
int main() {
Node n(3);
// 10 - 3 = 7์ด ๋ฆฌํด๋๋ค.
std::cout << 10 * n << std::endl;
// 10 * 3 = 30์ด ๋ฆฌํด๋๋ค.
std::cout << 10.0 * n << std::endl;
return 1;
}
์ด๋ ๊ฒ ๋ฉค๋ฒ ํจ์๋ก ์ ์ํ ์ ์๋ Operator overloading ๋ฐฉ์๊ณผ ๊ทธ๋ ์ง ์์ Operator๊ฐ ๋ฐ๋ก ๋๋ ์ ์๋ค. ์๋๋ ๊ทธ์ ๊ดํ ํ์ด๋ค.