[C++] OOP (1) 개념 / namespace
C++은 C에 객체지향 개념이 추가된 언어로 이해하면 편하다.
문법과 메모리 관리 등 여러 부분이 C와 유사하지만, char 리터럴의 바이트 크기와 같이 다른 부분이 있어 아예 동일하지는 않다.
Class & Object
클래스는 설계도이고, Object는 설계도를 통해 만든 결과물이다.
Abstraction
사용자가 객체의 구체적인 구현을 몰라도 기능을 사용할 수 있도록 한다.
메서드를 호출하면 메서드가 실행돼 실행 결과를 얻지만, 사용자는 메서드가 어떻게 구현됐는지 몰라도 된다.
Encapsulation
객체 내부의 상태를 검증되지 않은 접근으로부터 보호한다.
즉, 사용자가 객체 내부 상태에 직접 접근하는걸 방지하고 메서드를 통해 접근하는 등 접근 방법을 제한한다.
Inheritance
객체가 다른 객체의 속성을 그대로 이어받을 수 있도록 한다.
Polymorphism
하나의 객체가 다양한 형태를 가질 수 있도록 한다.
Car* car = new Bus("myBus") / 오버라이딩 / 오버로딩 등..
객체지향의 6가지 개념이다.
메모리를 깊게 다룰 수 있는 C의 특성과 객체지향 개념을 사용해 더 깊은 프로그래밍을 시작하자.
class Door{};
class Car{
public:
Car(std::string name) : name_(name) {}
std::string name() {
return name_;
}
Door GetDoor(int index){
return doors_[index];
}
private:
std::string name_;
Door doors_[4];
};
C++은 자바와 사용하는 방법이 좀 다르다.
클래스 내부 요소들에 대한 접근 제어자를 한 번에 지정하고, 클래스의 마지막에 세미콜론을 찍어줘야 한다.
위의 예시처럼 클래스(A) 내부에 클래스(B)가 존재할 때 B클래스의 기본 생성자가 없으면 오류를 뱉는다.
int main(){
Car car1("a"); // direct
Car car2 = Car("b"); // direct
Car car3 = "c"; // implicit conversion
Car car4 = (Car) "d"; // explicit conversion
return 0;
}
위의 네 가지 코드는 모두 실행 결과가 같다.
자바에는 default 접근제어자가 있지만, C++에는 default가 없다.
class에서 접근 제어자를 생략 시 private로 지정되고, struct에서 접근 제어자를 생략 시 public으로 지정된다.
private : 해당 클래스 내부에서만 사용
protected : 해당 클래스와 자손 클래스에서만 사용
public : 어디서든 가능
C++에서 생성자는 오버로딩을 지원하고, user-defined 생성자가 없다면 기본 생성자를 컴파일러가 만들어준다.
여기까지는 자바와 유사하지만, 좀 다른 부분이 있다.
생성자는 위의 구조로 작성하고, Default / Implicit / Explicit / Copy 총 4가지 종류의 생성자가 있다.
자바와 다른 점으로 C++은 생성자에 초기화 필드를 제공한다. (initialization list)
멤버필드명과 초기화 할 값을 입력받는다.
ex) Car(std::string name) : name_(name) {}
body-statement에는 const가 붙은 멤버변수들을 초기화 할 수 없지만, 초기화 필드에서는 const가 붙은 멤버변수들을 초기화 할 수 있다.
멤버변수의 초기화는 initialization list에서 진행하고, 나머지 작업은 body-statement에서 진행하자.
Default Constructor
Car() {}
자바와 동일하다. user-defined 생성자가 없을 때만 컴파일러가 만들어준다.
Implicit Conversion Constructor
Car(std::string name) : name_(name) {}
하나의 파라미터를 가지고 explicit 키워드가 없다.
Google C++ guide에서 추천하지 않는 방법이다.
생성자의 파라미터가 2개 이상인 경우는
Car car = {a,b,c} 이런 식으로 생성한다.
Explicit Conversion Constructor
explicit Car(std::string name) : name_(name) {}
하나의 파라미터를 가지고 explicit 키워드가 붙어있다.
타입으로 객체를 만드는 작업을 금지한다.
즉, Explicit Conversion Constructor를 사용하면
Car car3 = "c";
이렇게 객체를 만들 수 없다.
Car car4 = (Car)"d" 는 가능하다.
Google C++ guide에서 권장하는 방법이다.
Copy Constructor
객체를 복사할 때 사용되는 생성자이다.
user-defined copy constructor 가 없으면 컴파일러가 알아서 추가해준다. (기본 생성자와 독립적으로 동작한다)
Car(const Car& car) : name_(car.name_) {
for(int i=0; i<4; i++){
doors_[i] = car.doors_[i];
}
}
이런 식으로 정의되고
Car car5;
Car car6(car5);
Car car7 = Car(car6);
Car car8 = car7;
이렇게 사용한다.
이 때 자바와는 달리 주소값이 복사되지 않고 새로 객체를 만들어서 할당됨에 주의하자.
car8의 멤버를 수정해도 car7의 멤버는 수정되지 않는다.
this는 자바와 비슷하다.
receiver object의 포인터 역할을 한다. (this->a 표현을 자주 사용한다. 포인터니까 ->)
this는 const가 붙어 값을 다시 할당 할 수 없다.
잘 사용되지는 않지만, C++에는 친구 관계가 있다.
단방향 관계이고 친구 관계로 지정된 객체는 모든 멤버를 사용할 수 있다.
고양이는 사람을 사용하지만 사람은 고양이를 사용할 수 없다. (단방향)
C++ 에서는 객체의 선언과 정의를 철저하게 분리해야 한다.
헤더 파일(.h)에는 선언을, 소스 파일(.cpp)에서는 헤더 파일을 include로 가져오고 정의를 작성하는 방식으로 분리한다.
이후 컴파일 할 때는 링커로 헤더파일을 연결해주는 작업을 거친다.
객체를 작성할 때는 접근 제어자를 public - protected - private 순으로 작성하고, 표기법을 지켜서 작성하자.
C++에는 namespace라는 개념이 있다.
자바의 패키지 개념과 유사하다.
클래스와 유사하지만 객체를 만들 수는 없고, 코드의 집합. (메서드와 변수의 집합) 정도로 이해하면 된다.
namespace를 여러 개 사용해 이름이 같은 변수 / 클래스 / 메서드를 여러 개 만들어서 사용할 수 있다.
namespace를 중첩해서 사용하는것도 가능하고 이름이 중복될 때 가장 가까운 요소를 채택한다. (전역변수는 가장 마지막에 고려한다)
당연히 namespace 내부 요소들끼리는 중복된 이름을 가지면 안 되고, 각각 다른 namespace 간에는 중복된 이름을 가져도 상관없다.
namespace ns2{
int sa = 203;
}
namespace ns2{
int sa2 = 20;
}
namespace를 이렇게 정의하면 ns2가 합쳐져 int sa와 int sa2를 모두 가지게 된다.
using namespace a; 대신 using a::(사용하려는 멤버) 이렇게 사용하는 편이 합리적이다. (중복을 피하기 위함)
namespace ns1{
int a = 10;
namespace ns2{
int b = 10;
}
namespace ns3{
int c = 10;
namespace ns4{
int z = 100;
}
}
}
namespace ns4{
int z = 10;
}
int main(){
std::cout << ns4::z << "\n"; // 10
std::cout << ns1::ns3::ns4::z << "\n"; // 100
}
namespace 내부 요소들에 대해서만 중복을 피하면 된다.
'Programming Language > C++' 카테고리의 다른 글
[C++] OOP (4) Type Casting (0) | 2022.10.19 |
---|---|
[C++] OOP (3) Inheritance / 연산자 오버로딩 (1) | 2022.10.12 |
[C++] C++과 Java (1) | 2022.10.05 |
[C++] Memory Allocation / static (0) | 2022.10.05 |
[C++] OOP (2) 함수 오버로딩 / 함수 호출 (0) | 2022.09.28 |
댓글
이 글 공유하기
다른 글
-
[C++] OOP (3) Inheritance / 연산자 오버로딩
[C++] OOP (3) Inheritance / 연산자 오버로딩
2022.10.12 -
[C++] C++과 Java
[C++] C++과 Java
2022.10.05 -
[C++] Memory Allocation / static
[C++] Memory Allocation / static
2022.10.05 -
[C++] OOP (2) 함수 오버로딩 / 함수 호출
[C++] OOP (2) 함수 오버로딩 / 함수 호출
2022.09.28