[모던C++입문] 6.1 기본 원칙

    6. 객채 지향 프로그래밍

    6.1 기본 원칙

    • 추상화(Abstraction) : 클래스는 개체의 특성과 멤버 함수를 정의, 클래스는 특성의 불변성을 지정할 수도 있음
    • 캡슐화(Encapsulation) : 구현의 세부 사항을 숨기는 원칙. 내부 특성은 불변성을 위반하지 않기 위해 직접 접근 할 수 없으며, 클래스의 멤버 함수를 통해서만 접근할 수 있다.
    • 상속(Inheritance) : 파생 클래스가 기본 클래스의 모든 멤버 변수와 멤버 함수를 포함한다는 원칙
    • 다형성(Polymorphism) : 문맥이나 매개변수에 따라 해석하는 식별자의 능력

    기본 클래스와 파생 클래스

    class person
    {
    public:
        person() { }
        explicit person(const string& name) : name(name) { }
    
        void set_name(const streing& n) { name = n; }
        string get_name() const { return name; }
    
        void all_info() const
        { cout << "[person] My name is " << name << endl; }
    private:
        string name;
    }
    
    class student : public person
    {
    public:
        student(const string& name, const string& passed)
            : person(name), passed(passed) { }
    
        void all_info() const {
            cout << "[student] My name is " << get_name() << endl;
            cout << "I passed the following grades: " << passed << endl;
        }
    
    private:
        string passed;
    }
    
    person mark("Mark Markson");
    mark.all_info();
    
    student tom("Tom Tomson", "Algebra, Analysis");
    tom.all_info();
    
    //p, pr, pp 는 전부 같음
    person p(&tom);
    person& pr = tom;
    person* pp = &tom;
    
    p.all_info();
    pr.all_info();
    pp->all_info();
    
    //실행 결과
    /*
    [person] My name is Mark Markson
    [student] My name is Tom Tomson
    I passed the following grades : Algebra, Analysis
    [person] My name is Tom Tomson
    [person] My name is Tom Tomson
    [person] My name is Tom Tomson
    */

    생성자 상속

    • 생성자는 기본 클래스에서 암시적으로 상속되지 않는 멤버함수
    class person
    {
    public:
        explicit person(const string& name) : name(name) { }
        //...
    };
    
    class student : public person
    {};     // string으로 정의된 생성자가 없다.
    
    int main()
    {
        student tom("Tom Tomson"); //오류 : string 생성자가 없다
    }
    
    //C++11에서는 using을 통해 기본 클래스의 모든 생성자를 상속 받을수 있다.
    class student : public person
    {
        using person::person;
    };

    가상 함수와 다형성 클래스

    • 다형성 타입은 하나 이상의 가상 함수를 포함하는 클래스 이다.
    • 다형성 타입은 항상 레퍼런스나 (스마트) 포인터로 전달해야 한다.
    class person
    {
        virtual void all_info() const
        { cout << "[person] My name is " << name << endl; }
    }
    
    class student : public person
    {
        virtual void all_info() const
        {
            person::all_info(); //person클래스의 all_info를 호출
            cout << "[student] My name is " << get_name() << endl;
            cout << "I passed the following grades: " << passed << endl;
        }
    }
    
    p.all_info();
    pr.all_info();
    pp->all_info();
    
    //이전과 동일한 실행코드 출력 결과
    /*
    [person]   My name is Tom Tomson
    [person]   My name is Tom Tomson
    [student]  My name is Tom Tomson
        I passed the following grades: Algebra, Analysis
    [person]   My name is Tom Tomson
    [student]  My name is Tom Tomson
        I passed the following grades: Algebra, Analysis
    */

    명시적 오버라이딩

    • C++11에서 추가된 override 특성을 사용하면 기본 클래스의 virtual 함수를 오버라이드 한다고 선언할 수 있다.
    • C++11에서 추가된 다른 특성인 final은 가상 멤버 함수를 오버라이드 할 수 없다고 선언한다.

    추상 클래스

    • = 0 로 선언하는 virtual 함수를 순수 가상 함수(Pure Virtual Function)라고 한다.
    • 순수 가상 함수를 포함하는 클래스를 추상 클래스(Abstract Class)라고 한다.
    class creature
    {
        virtual void all_info() const = 0;
    }
    
    class person : public creature
    { ... }
    
    int main()
    {
        creature som_beast; //오류 : 추상 클래스
    }

    상속을 통한 펑터

    • 성능 : operator()는 항상 가상 함수로 호출된다.
    • 적용 가능성: functor_base에서 파생된 클래스만 인수로 사용 가능
    • 펑터는 가능하면 제네릭 방식을 사용해 구현해야한다.
    struct functor_base
    {
        virtual double operator() (double x) const = 0;
    };
    
    double finite_difference(functor_base const& f, double x, double h)
    {
        return (f(x+h) - f(x)) / h;
    }
    
    class para_sin_plus_cos : public functor_base
    {
    public:
        para_sin_plus_cos(double p) : alpha(p) { }
    
        virtual double operaotr() (double x) const override
        { return sin(alpha * x) + cos(x); }
    
    private:
        double alpha;
    }
    
    int main()
    {
        para_sin_plus_cos sin_1(1.0);
        cout << finite_difference(sin_1, 1., 0.001) << endl;
        double df1 = finite_difference(para_sin_plus_cos(2.), 1., 0.001),
        df0 = finite_difference(para_sin_plus_cos(2.),0., 0.001);
    }
    반응형

    댓글

    Designed by JB FACTORY