class Fraction
{
private:
	int m_numerator; // 여기서 초기화값 설정 가능
	int m_denominator;
public:
    //생성자
    //외부에서 호출하려고 쓰는 것이 아님. 선언과 동시에 실행됨.
    // 생성자를 안써주면 Fraction(){}과 같이 아무일도 안하는 생성자가 있음!
    Fraction()
    {
    	m_numerator = 1;
        m_denominator = 1;
    }
    // 이렇게 파라미터가 없는 생성자를 써주거나 아래처럼 기본값 오버로딩
    // 하지만 둘다 쓸 경우 둘 중에 뭘 써야 할지 몰라서 에러 발생
    
    Fraction(const int& num_in=1, const int& den_in=1)
    {
        m_numerator = 0; // 반환 데이터 타입 없음. class 이름과 동일하면 생성자(Constructor)
        m_denominator = 1;
    }
    
	void print()
	{
		cout << m_numerator << " / " << m_denominator << "\n";
	}
}

int main()
{
	//Fraction frac; // 생성자의 파라미터가 없을 경우 함수와 헷갈리기 때문에 () 생략.
    // 
	//frac.print(); // 초기화가 되지 않아 문제 발생.
    Fraction one_third(1,3);
    // Fraction one_thirds = Fraction{1,3};
    // Fraction one_thirds{1,3};
    //Fraction one_thirds{1,3}과 one_thirds(1,3) 의 차이
    // Fraction one_thirds{1,3} -> uniform initialization은 데이터 타입을 바꿀 수 없다. 좀 더 엄격한 초기화
    // 또, member가 public일 경우 생성자 없이 처리 가능.
    // 생성자가 있을 경우 생성자를 따라간다.
    
    // one_thirds(1.0,3) -> 데이터 타입 변환 가능
    
    
    one_third.print();
    
    
}
class Second
{
public:
    Second()
    {
        cout << "class Second constructor()" << "\n";
    }
};

class First
{
    Second sec;
    
public:
    First()
    {
        cout << "class First constructor()" << "\n";
    }
}

int main()
{
    First fir;
    
    return 0;
    
    //class Second constructor()
    //class First constructor()
    
    // 멤버를 먼저 초기화 해주기 때문에 Second가 먼저 생성
}