본문 바로가기
C++

[C++] 클래스 (Class)/ 객체 (Object)/, 접근지정자(Access modifier)public, protected, private/ 여러 종류 생성자(Constructor)default, Implicitly, Explicitly, Copy/+ 예시코드

by 유노brain 2023. 10. 25.
반응형

클래스 선언 (Class declaration)

클래스 선언은 다음과 같이 됩니다.

class Car{
 
   public :
   Car(std::string name, int speed, std::string color): name_(name),
         speed_(speed), color_(color) {}

   int speed_up(int km){
         speed_ += km;
         return speed_;
   }
   
   private:
   std::string name_;
   int speed_;
   std::string color_;
}; 
// 클래스 끝 ";" 잊지말기

 

클래스 선언에 있어서 끝에 ";"을 잊으면 안됩니다.

 

객체 생성 (Object creation)

객체를 생성하는 방식에는 2가지 방법이 있습니다.

첫 번째는 직접 초기화(Direct initialization) 

두 번째는 변환(Conversion)입니다.

 

직접 초기화 방법

직접 초기화 방법은 암시적(Implicitly)으로 선언할 수 있습니다.

아래의 경우 암시적으로 Car클래스에서 생성자를 불러온 것입니다.

Car car("mycar")

 

위와 다르게 명시적(explicitly)으로도 객체를 생성할 수 있습니다.

아래는 Car 클래스에서 생성자를 명시적으로 불러온 것입니다.

Car car = Car("mycar")

 

 

변환

아래는 문자열의 값을 클래스의 객체로 암시적(Implicitly)으로 변환을 통해 생성한 것입니다.

Car car = std::string("my car")

 

위와 다르게 아래는 명시적(explicitly)으로 변환을 통해 생성한 것입니다.

Car car = (Car) "mycar"

 

요약
int main(){
   Car car1("hyundai"); // 암시적인 직접 초기화로 객체 생성
   Car car2 = car("BMW"); // 명시적인 직접 초기화로 객체 생성
   Car car3 = "Benz"s; // 암시적 변환으로 객체 생성
   Car car4 = (car) "Kia"; //명시적 변환으로 객체 생성
}

 

 

접근 지정자(Access modifier)

클래스 안에서의 접근 지정자 종류는 아래와 같이 3가지가 존재합니다.

private, protected, public

접근을 지정하는데에 있어서 private가 보안에 있어가장 강력합니다.

반대로 public은 어디에서나 접근이 가능해 보안이 약합니다.

protected의 경우 private와 public의 중간이 되겠습니다.

 

private

private는 오직 클래스 안에서만 멤버변수의 접근을 허락합니다.

 

protected

protected의 경우 클래스 내부의 접근뿐만 아니라 자식 클래스에서도 접근이 가능합니다.

 

public

public의 경우 멤버 어디서든 접근이 가능합니다.

 

예시코드

아래의 예시코드를 보면 설명드리겠습니다.

#include <iostream>
#include <string>

class Car{
 
   public :
   Car(std::string name, int speed, std::string color): name_(name),
         speed_(speed), color_(color) {}


   std::string name(){
      return name_;
   }
   int speed_up(int km){
         speed_ += km;
         return speed_;
   }
   
   private:
   std::string name_;
   int speed_;
   std::string color_;
};

// 상속을 받을 때는 아래와 같이 상속을 받는다.
class Bus : public Car{
   public:
    Bus(std::string name, int speed, std::string color, int money):Car(name,speed,color), money_(money){}

   int Charge(int bill) {
      money_ += bill;
      return money_;
   }
   
   private:
   int money_;
};

int main() {
   Car my_car("hyundai", 150, "yellow");
   std::string name1 = my_car.name_; //private 멤버로 컴파일 시점에서 에러가 발생합니다.
   std::string name2 = my_car.name(); //OK
   std::cout<<name1<<std::endl;
   std::cout<<name2<<std::endl;
   return 0;
}



아래에서 main 클래스에서 name1과 name2를 비교해 보겠습니다.

name1의 경우 my_car.name_을 받는데요.

name_의 경우 Car 클래스에서 private안에 선언되어 있는 것을 알 수 있습니다.

그렇기 때문에 name1의 경우 컴파일 에러가 발생하게 됩니다.

 

반면에 name()의 경우 Car 클래스에서 public으로 선언되어 있는 것을 확인할 수 있습니다.

즉 public으로 선언이 되었기 때문에 정상적으로 작동합니다.

 

 

생성자 (Constructor)

생성자는 객체를 초기화하는 역할을 합니다.

멤버필드는 생성자 안에서 초기화됩니다.

 

생성자는 아래처럼 여러 개로 정의될 수 있습니다.

- Default constructor (기본생성자)

- Implicit conversion constructor (암시적 변환 생성자)

- Explicit conversion constructor (명시적 변환 생성자)

- Copy constructor (생성자 복사)

 

 

Default constructor(기본 생성자)

기본생성자의 경우 매개변수가 아무것도 없는 것을 뜻합니다.

컴파일러에서 자동적으로 기본 생성자를 생성해 줍니다.

(위 문장은 사용자 정의 생성자가 없는 경우에만 이루어집니다.)

모든 멤버 필드의 기본 생성자를 암시적(implicitly)으로 호출합니다.

멤버필드에 기본 생성자가 없을 경우 컴파일 에러가 발생합니다.

 

예시코드

아래의 코드는 기본 생성자에 대한 예시코드입니다.

#include <iostream>
#include <string>

class Car{
   public :
  Car() : name_("mycar") {}

   private:
   std::string name_;
   int speed_;
   std::string color_;
};

int main() {
   Car car1;
   return 0;
}

 

 

 암시적 변환 생성자 (Implicit conversion constructor)

생성자에 매개변수 하나가 있고 명시적(explicit)으로 선언되지 않았다면 암시적 변환 생성자(Implicit conversion constructor)입니다.

매개변수 타입의 값이 클래스의 객체로 변형되는 것을 허용합니다.

C++11 이후로는 매개변수가 없거나 하나 또는 여러 개를 가질 수 있습니다.

즉 위의 말은 명시적 변환 생성자가 아니면 암시적 변환 생성자라는 것을 뜻합니다.

 

구글 C++ 스타일에서는 암시적 변환 생성자를 추천하지 않습니다.

예시코드
#include <iostream>
#include <string>

class Car{
   public :
   Car(std::string name) : name_(name){} // 암시적 변환 생성자

   private:
   std::string name_;

};

int main() {
   Car car1("hyundai");
   Car car2 = Car("BMW");
   // Car car3 = "Benz"s; <- 이건 안됨
   Car car4 = (Car)"Kia";
   return 0;
}



 

Explicit conversion constructor (명시적 변환 생성자)

생성자에 매개변수 하나가 있고 명시적(explicit)으로 선언되었다면 명시적 변환 생성자(Explicit conversion constructor)입니다.

매개변수 타입의 값이 클래스의 객체로 변형되는 것을 허용하지 않습니다.

C++11 이후로는 매개변수가 없거나 하나 또는 여러 개를 가질 수 있습니다.

이는 명시적 키워드로 선언된 모든 생성자는 명시적 변환 생성자입니다.

 

구글 C++ 스타일에서는 명시적 변환으로 생성자를 선언하는 것을 추천합니다.

예시코드
#include <iostream>
#include <string>

class Car{
   public :
   explicit Car(std::string name) : name_(name){} // 명시적 변환 생성자

   private:
   std::string name_;

};


int main() {
   Car car1("hyundai");
   Car car2 = Car("BMW");
   Car car4 = (Car)"Kia";
   return 0;
}

 

 

Copy constructor (생성자 복사)

Copy constructor는 객체를 복사합니다.

모든 멤버필드의 값들을 복사합니다.

 

컴파일러는 자동적으로 기본 생성자를 생성합니다.

(사용자 정의  복사 생성자가 없을 경우에만)

(멤버필드의 얕은 복사를 생성한다.)

 

예시코드
#include <iostream>
#include <string>

class Car1{
    public:
    Car1() : name_("mycar"){}
    Car1(const Car1& car) : name_(car.name_){}

    std::string name(){
        return name_;
    }

    private:
    std::string name_;
   
};


int main(){
    Car1 car1;
    Car1 car2(car1);
    Car1 car3(car2);
    Car1 car4 = car3;

    std::cout<<car1.name()<<std::endl;
    std::cout<<car2.name()<<std::endl;
    std::cout<<car3.name()<<std::endl;
    std::cout<<car4.name()<<std::endl;
}

 

 


해더파일과 cpp파일 나누어서 코드 작성해보기

car.h 
#include <iostream>
#include <string>

class Car{
   public :
   explicit Car(std::string name); // 명시적 변환 생성자

   std::string name() const;
   private:
   std::string name_;

};
car.cpp
#include <iostream>
#include <string>
#include "car.h"


Car::Car(std::string name):name_(name){}

std::string Car::name() const{

   return name_;
}


int main() {
   Car car1("hyundai");
   Car car2 = Car("BMW");
   Car car3 = (Car)"Kia";

   

   std::cout<< car1.name()<<std::endl;
   std::cout<< car2.name()<<std::endl;
   std::cout<< car3.name()<<std::endl;
   return 0;
}
반응형

댓글