C++) 복사 생성자
복사 생성자 복사 생성자는 객체의 사본을 생성할 때 자동으로 호출되는 생성자 함수이다. 매개변수로 인스턴스의 포인터를 넘겨주어야하며, 이는 복사본의 원본 인스턴스에 대한 참조에 의해 쓰인다. #include using namespace std; class MyData { public: MyData() { // 디폴트 생성자 default constructor cout
복사 생성자 복사 생성자는 객체의 사본을 생성할 때 자동으로 호출되는 생성자 함수이다. 매개변수로 인스턴스의 포인터를 넘겨주어야하며, 이는 복사본의 원본 인스턴스에 대한 참조에 의해 쓰인다. #include using namespace std; class MyData { public: MyData() { // 디폴트 생성자 default constructor cout
정적 멤버 클래스 내 전역 변수나 전역 함수와 동일한 역할을 하는 클래스의 멤버로써 접두어로 static을 붙여서 선언한다. 클래스 자체에 내장되어 있으므로 인스턴스의 선언 없이 호출이 가능하고, 인스턴스의 선언 자체가 필요 없으므로 this를 이용해 참조할 수 없다. (애초에 인스턴스에 있는게 아니니까) #include class Test { public: Test(int data) : nData(data) { nCount++; } // Test 클래스로 인스턴스를 생성하면 nCount가 증가함. int getData() { return this->nData; } // 인스턴스 멤버 static int getCount() { return nCount; // nData에 접근할 수 없음. } // 정적 ..
생성자 다중 정의 클래스 생성자는 다중정의가 된다. class MyData { public: MyData(int nParam): nData(nParam){} MyData(int x, int y): nData(x + y){} void printData() { std::cout x = x; } MyPoint(int x, int y): MyPoint(x) { if (y > 200) y = 200; this->y = y; } void printCoord() { std::cout
디폴트 생성자 디폴트 생성자는 클래스가 선언되었을 때 자동으로 호출되어 클래스의 멤버를 구성해주는 함수이다. 디폴트 생성자의 경우에는 클래스를 선언할 때 매개변수에 특정값을 넣을 필요가 없으므로, 이 점에서 다른 생성자들과 차이점이 있다. (매개변수 없이 알아서 호출되는 함수이기 때문) 사실 말만 복잡한 것이다. 단순히 디폴트 생성자를 사용한다는 것은 생성자를 명시하지 않아도 좋다는 것이며, 선언 시점에 매개변수를 넘길 필요가 없다는 뜻이기도 하다. class DefaultConstructor { public: DefaultConstructor():str1("디폴트"), str2("생성자") {} //또는 아래와 같이 선언 //DefaultConstructor() { //str1 = 30; //str2 ..
디폴트 생성자 생성자는 객체가 생성되는 시점에 자동으로 호출되는 멤버 함수. (객체의 생성은 인스턴스 선언 및 new 연산에 따른 동적 생성 두 경우에 의해 생긴다.) 전역 인스턴스가 존재할 경우, main() 함수보다 생성자가 먼저 호출되며, 생성자는 다중 정의가 가능하다. 소멸자 소멸자는 객체가 소멸하는 시점에 자동으로 호출되며 다중 정의가 불가능하다. main()함수가 끝난 뒤에도 호출될 수 있다. 코드 #include class Test { public: Test() { std::cout
클래스 기본 문법 클래스는 관계에 대해 일절 고려하지 않는다면 함수를 포함하는 구조체라고 볼 수 있다. 클래스에는 생성자, 소멸자 등 문법상 자동으로 호출되는 함수가 존재하며, 이 때문에 C++에서는 Called by ~ 가 중요해진다. (생성자, 소멸자 등의 자동호출 시기를 아는 것이 도움이 된다.) 또한 클래스의 구성요소도 구조체처럼 멤버라고 지칭한다. #include class UserData { public: // 접근제어 지시자 int age; char name[32]; void print() { printf("%d, %s", age, name); } }; int main() { UserData user = { 30, "2DC" }; user.print(); return 0; } 참고로 클래스 ..
C++ 스타일 C 코드 // C++ 스타일 C 코드 예 #include typedef struct USERDATA { int age; char name[32]; void(*print)(struct USERDATA* pUser); } void printData(USERDATA* pUser) { printf("%d, %s\n", pUser->age, pUser->name); } int main() { USERDATA user = { 30, "2DC", printData }; user.print(&user); return 0; } 위의 코드는 C언어를 C++ 스타일로 짜본 것이다. C언어는 클래스/객체 대신 구조체를 사용하고, 구조체는 기본적으로 메서드를 멤버로 둘 수 없다. 따라서 함수 포인터 멤버를 구조체..
객체란 무엇인가 (깊게 들어갈 필요가 있을까? ...) 객체는 OOP 환경에서 소프트웨어(소스코드)를 구성하는 단위 요소이고 변수 및 그와 관련된 메서드가 모여 이뤄진 하나의 집합체이다. (구조체와는 약간 다르다. 구조체는 변수만 포함하고, 객체는 변수와 함수(메서드)까지 포함한다.) C++에서는 객체를 클래스(Class)로 기술하며, 클래스는 C언어의 구조체와 유사한, 변수와 함수를 멤버로 갖는 하나의 틀이다. #include class USERDATA { public: int age; char name[32]; void printUser() { printf("%d %s", age, name); } }; int main() { USERDATA DC = { 30, "2DC" }; DC.printUser(..
Name Mangling 맹글링은 영단어로 '난도질하다'라는 의미이다. 즉, 네임 맹글링은 말 그대로 어떤 이름을 난도질해버리는 것이다. C++의 식별자 이름은 컴파일러에 의해 C언어처럼 유일한 이름으로 변경된다. namespace의 구분에 의해 중복되는 식별자가 많아질 수 있으므로 이런 기능이 도입되었고, 덕분에 함수 다중 정의(Overloading)가 동작할 수 있게 되었다. 네임 맹글링은 링크 타임의 오류를 디버깅할 때 반드시 알아야 하는 부분이다. #include using namespace std; extern "C" void noManglingFunc() // 네임 맹글링을 시행하지 않음 { cout
Namespace C++가 지원하는 각종 요소들(변수, 함수, 클래스 및 각종 선언 등)을 한 범주로 묶어주기 위한 문법으로 중첩이 가능하다. 선언할때는 식별자 이름 앞에 ::을 붙여서 표기한다. 사실상 C++의 모든 변수나 함수는 C++ 문법 상 namespace에 속한다고 할 수 있는데, 예시로 모든 전역변수나 함수는 global namespace에 해당한다. #include using namespace std; // 디폴트 네임스페이스가 std가 된다. int nData = 999; // global namespace에 속하는 전역변수 namespace Test // Test namespace 선언 { int nData = 100; // Test::nData void testFunc() // Tes..