본문 바로가기

C++

c++ 4 (오버라이드 / 오버로드)

오버로드 (Overload)

 

동일한 이름을 갖고있지만 다른 동작을 하게 만드는 것

대표적으로 함수 오버로드가 있다.

 

함수 이름은 함수명을 포함한 파라미터의 타입의 나열들 까지 포함

-> 파라미터의 개수나 타입이 다르다면 서로 다른 함수명이 된다.

 

함수 오버로드를 통해 이름은 같지만 서로 다른 파라미터에 대해 각각의 동작을 따로 지정해줄 수 있다. 

파라미터의 개수와 타입을 통해서 어떤 함수가 불러 지는지를 특정할 수 있다.

 

 

클래스에서의 함수 오버로딩

이는 클래스 멤버함수에서도 동일하게 작용하게 된다.

또한 클래스 생성자에 대해서도 동일하게 작용할 수 있는데

이는 클래스가 여러 개의 생성자를 가질 수 있다는 것을 의미

 

클래스 생성자도 어찌보면 함수라 할 수 있고,

클래스 생성자도 파라미터의 타입과 개수를 통해 어떤 생성자를 호출할 수 있을지 결정할 수 있기 때문

 

클래스 생성자가 여러 개가 있을 경우 하나의 생성자만 호출해주면 된다.

 

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>


class Student {
public:
    int student_no;
    char student_name[100];
    
    Student() { // 초기화
        student_no = 0;
        strcpy(student_name, "아무개");
    }
    
    Student (int studentNo, const char* student_name) {
        this->student_no = studentNo;
        strcpy(this->student_name, student_name);
    }
    
    void printInfo() {
        printf("%s 학생의 학생번호 : %d\n", student_name, student_no);
    }
};


int main(){
    Student* s1 = new Student();
    Student* s2 = new Student(10, "홍길동"); // 10과 홍길동을 이용해 위의 파라미터가 있는 멤버 변수들을 초기화 해줬다.
    
    s2->printInfo(); // s2 출력
    s1->printInfo(); // s1 출력
    
    return 0;
}

 

연산자에서의 오버로딩

연산자 또한 오버로딩을 할 수 있는데

동적 클래스가 아닌 Stack 기반 클래스 인스턴스에 동작하는 연산자를 오버로딩 할 수 있다.

 

연산자 오버로딩의 가장 좋은 점은

연산자 오버로딩을 통해 우리가 현실세계에서 쓰는 것과 같은 표현을 컴퓨터에게 입력할 수 있다는 점이다.

연산자 오버로딩을 하게 되면 좌표, 벡터, 문자열 등에 대한 스택 기반 클래스 인스턴스에

덧셈 곱셈 뺄셈 등등의 여러 연산자를 집어넣을 수 있다.

본래 연산자라는 것은 어사인 (=) 연산자를 제외한 나머지 모든 연산은 '기본형 데이터 타입'에만 적용 가능

그런데 c++에서는 연산자 오버로딩을 통해 이 장벽을 넘을 수 있다.

 

다른 언어에서의 연산자 오버로딩

 

c / c++/ c#을 제외하면 다른 언어에서는 연산자 오버로딩을 마음껏 할 수 있는 환경을 찾아보기 어렵다.

특히 Java 같은 경우 이런 Vector 연산을 위해 긴 코드를 작성하거나 '멤버함수.add(...)'등을 호출하여 해결

 

 

2차원 벡터 연산

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>


class Vector {
public:
    float x;
    float y;
    
    Vector(float x, float y){
        this->x = x;
        this->y = y;
    }
    
    Vector() { // 아무것도 받지 않는 생성자
        x = 0.0f;
        y = 0.0f;
    }
    
    void printInfo(){
        printf("%.2f, %.2f", x, y);
    }
};


Vector operator+(Vector& v_1, Vector& v_2){
    return Vector(v_1.x + v_2.x, v_1.y + v_2.y);
}


int main(){
    
    Vector v1 = Vector(100, 200);
    Vector v2 = Vector(1, 2);
    
    Vector v3 = v1 + v2;
    v3.printInfo(); // 정적으로 만들어짐 연산자 오버로딩은 정적은 클래스 인스턴스에서만 동작
    
    return 0;
}

 

3차원 벡터 클래스 (각각의 좌표에 해당하는 숫자에 10 곱하기)

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>


class Vector3 {
public:
    float x;
    float y;
    float z;
    
    Vector3(float x, float y, float z){
        this->x = x;
        this->y = y;
        this->z = z;
    }
    
    Vector3() { // 아무것도 받지 않는 생성자
        x = 0;
        y = 0;
        z = 0;
    }
    
    void printInfo(){
        printf("%.2f, %.2f, %.2f", x, y, z);
    }
};


Vector3 operator*(Vector3& v1, float s){
    return Vector3(v1.x *s, v1.y *s, v1.z *s);
}


int main(){
    
    Vector3 v = Vector3(10, 20, 30);
    Vector3 result = v * 10;
    
    result.printInfo(); 
    
    return 0;
}

 

스칼라 (Scalar)

물리 / 수학적으로 어떤 양적인 수치를 의미

프로그래밍 초기에는 단순히 그냥 실수값이라 생각해도 무방

 

 

오버라이드 (Override) , 오버라이딩 (Overriding)

오버라이드 또는 오버라이딩은

부모 클래스의 함수의 정의를 자식 클래스에서 새로 덮어쓰는 것을 의미

(오버로딩은 완전히 서로 다른 이름을 만들어내는 것)

 

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>


class Animal {
public:
    int legs;
    char name[20];
    
    Animal(int legs, const char* name) {
        // 초기화
        this->legs = legs;
        strcpy(this->name, name);
    }
    void printInfo(){
        printf("다리: %d, 이름 : %s\n", legs, name);
    }
};


class Human : public Animal{ // 상속관계에서만 동작하는게 오버라이드
public:
    char regist_no[40];
    
    Human(const char* regist_no) : Animal(2, "사람") { // 부모클래스에서 생성자를 정의했다면 그 생성자를 여기서 호출
        strcpy(this->regist_no, regist_no);
    }
    // Human에서 다리개수, 이름 뿐만 아니라 주민번호까지 출력 하고 싶은 경우 -> Human에서 똑같은 이름으로 함수 만들기
    void printInfo() { // 파라미터까지 똑같은 함수를 만들어 내는 것 : 오버라이드
        printf("이름: %s, 주민등록번호: %s\n", name, regist_no);
    }
};


int main(){
    
    Human* human = new Human("1234-5678");
    Animal* animal = new Animal(2, "닭");
    
    human->printInfo(); // 오버라이드로 함수를 덮어씌웠기 때문에 주민등록번호 함수 실행
    animal->printInfo(); // 다리와 이름만 나타남
    
    return 0;
}

 

 

과제형 연습 프로그래밍

3차원 행렬 Matrix를 선언하고 이 Matrix의 정적 클래스 인스턴스의 행렬합을 구하는

연산자 오버로딩 함수를 구현하고 결과 출력

 

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cstring>


class Matrix{
public:
    float v11, v12, v13;
    float v21, v22, v23;
    float v31, v32, v33;
    
    Matrix(float v11, float v12, float v13, float v21, float v22, float v23, float v31, float v32,float v33){
        this->v11 = v11;
        this->v12 = v12;
        this->v13 = v13;
        this->v21 = v21;
        this->v22 = v22;
        this->v23 = v23;
        this->v31 = v31;
        this->v32 = v32;
        this->v33 = v33;
    }
    
    void printInfo() {
        printf("%.2f, %.2f, %.2f\n", v11,v12,v13);
        printf("%.2f, %.2f, %.2f\n", v21,v22,v23);
        printf("%.2f, %.2f, %.2f\n", v31,v32,v33);
    }
};


// 연산자 오버로딩, 함수 선언
Matrix operator+(Matrix& m1, Matrix& m2);

#include "lala.hpp"


int main(){
    Matrix m1 = Matrix(1,2,3,4,5,6,7,8,9);
    Matrix m2 = Matrix(10,11,12,13,14,15,16,17,18);
    
    Matrix result = m1 + m2;
    
    result.printInfo();
    
    return 0;
}




// 연산자 오버로딩, 함수 몸체
Matrix operator+(Matrix& m1, Matrix& m2){
  return Matrix(
            m1.v11 + m2.v11, m1.v12 + m2.v12, m1.v13 + m2.v13,
            m1.v21 + m2.v21, m1.v22 + m2.v22, m1.v23 + m2.v23,
            m1.v31 + m2.v31, m1.v32 + m2.v32, m1.v33 + m2.v33
            );
}