템플릿

함수나 클래스에서 사용되는 변수가 다른함수나 클래스를 정의할때 변수의 type이 바뀌는 경우 template 클래스로 정의한다. 그리고 사용 되는 변수에 맞게 객체를 선언시 컴파일러가 알아서 해당하는 함수나 클래스를 생성하여준다.

템플릿 클레스

달라지는 부분은 총 네가지이다.

1.클래스 선언 앞부분.

2.함수 선언 앞부분.

3.함수 scope 부분.

4.변수 선언부

->모든 함수, 클래스 앞부분은 template<class T>를 써주자.

ex)

헤더파일 ```

#pragma once template 1.클래스 선언 앞부분에 템플레이트 정의삽입! class CPair { public: void Setm1(T ma);
T Getm1() const; CPair(T ma);

private: T m1; };

>cpp 파일

#include "stdafx.h"

#include "CPair.h" template ->2.함수선언 앞부분 정의 삽입! CPair::CPair(T ma) : m1(ma) ->3.함수 스코프 앞에 리턴타입t와 삽입! {

} template T CPair::Getm1() const { return m1; } template void CPair::Setm1(T ma) { m1 = ma; }

>main문

#include "stdafx.h"

#include "CPair.h";

#include "CPair.cpp"

#include

#include using namespace std;

int main() { CPair q1(10); ->변수선언을 벡터처럼 바꾸어줌!이것은 int형 q1! cout << q1.Getm1(); return 0; }

# 템플릿 함수

달라지는 부분은 총 세가지이다.

1.함수선언 앞부분

2.변수선언부

3.함수 정의 앞부분.

ex) template void swapValues(T& var1, T& var2);

int main() { //char a = 'a', b = 'b';

int a = 3, b = 4;
cout << "a=" << a << "b=" << b<<endl;
swapValues(a, b);
cout << "a=" << a << "b=" << b<<endl;

char c = 'c', d = 'd';
cout << "c=" << c << "d=" << d << endl;
swapValues(c, d);
cout << "c=" << c << "d=" << d<<endl<<endl;

return 0;

}

template void swapValues(T &r1, T &r2) { T temp; temp = r1; r1 = r2; r2 = temp; }

```

상속

사람이라는 객체와 학생,선생님,사부님이라는 객체가 있다.

학생, 선생님, 사부님은 모두 사람이라는 객체이며 동시에 각각의 특성을 지닌다.

즉 사람이라는 객체를 기반으로 각각의 또다른 특성이 있게된다.

이렇듯 클래스도 여러 객체가 반드시 한객체의 성질을 기반으로 만들어 졌을때 기반이 되는 클래스를 부모 클래스라 하며 이에대한 특성을 갖는 클래스를 자식클래스라 한다.

부모는 자식을 품지만 자식은 부모를 품지 못한다를 기억하자.(부모가 자식을 품을떄 부모에게 없는 변수나 함수는 slicing된다.ㄷ)

정의

class <클레스명> : <접근제한자> <상속받을 클레스명> {

자식클레스에서 추가로 설정해줄 맴버변수나 함수 만들기]

};

그렇다면 위에 <접근제한자> <상속받을 클레스명> 에서 접근제한자의 역할은 무엇일까??

  • private 상속

private로 상속시 private보다 넓은 접근 범위(protect,public)의 맴버변수및 함수들을 private접근 제한자로 변환시킨다는 의미이다.

즉 부모클래스의 private는 private로 유지가 되고 나머지 변수및 함수 모두 private 처리되므로 자식클래스 및 외부클레스 에서는 접근이 불가능하다.

  • protect로 상속

private는 그대로두고, protect보다 넓은 범위인 public을 protect로 변환한다.

protect의 상속은 조금 헷갈릴 수 있다.

protect로 상속하는 경우 부모클레스의 protect와 public 클레스 범위 의 함수나 변수를 사용 할 수 있다.(이때 public -> protect로 되겠지?)

하지만 protect는 외부 객체에서 참조가 불가능하다

예를들면

class 부모 {

protect:
    function ~;
    }

class 자식 :
protect : 부모
{

}

int main(){

자식.객체;

자식.function -->오류 발생!

}

'언어 > CPP(cpp)' 카테고리의 다른 글

템플릿  (0) 2018.02.06
오버라이딩  (0) 2018.02.06
동적배열과 이차원 동적배열  (0) 2018.02.06
const  (0) 2018.02.06
operator overloading(연산자 오버로딩)  (0) 2018.02.05

동적배열

c언어에서의 변수로 공간을 할당하기 위한 '함수' malloc 과 free 를 대신하여 c++에서는 공간 할당하기 위한 '연산자' new와 공간해제를 위한 delete 가 사용된다.

new

정의-1 길이로 초기화

<자료형>* 변수명1;
변수명1= new int [원하는 길이의 변수명];-->길이가 원하는길이의 변수명만큼의 길이로 정해짐

정의-2 값으로 초기화
변수명1= new int (원하는 값의 변수명);-->값이 원하는 값으로 초기화가 됌

-->참고로 두개를 동시해 사용하는것은 불가능하다.

정의-3 변수를 넣지않고 초기화

변수명1= new int;-->변수타입 6개정도가 0으로 할당되어 초기화됌

delete

정의

delete[] 변수명;

이차원 동적배열과 해제

이차원 동적 배열

정의
1.가로포인터할당

이차원포인터 = new <데이터타입>*[가로길이];
-->직역하자면 가로길이만큼의 배열인데 이는 각각 데이터 타입의 포인터를 담겠다를 의미.

2.세로길이 할당

for(int i=0;i<가로길이;i++){

    이차원포인터[i]=new int[세로길이];

}
-->각 가로의 포인터배열에 새로길이를 나타내는 포인터를 담아준다.

이차원 동적 배열 해제

정의
1.가로 해제

for(int i = 0 ; i<가로길이 ;i++){

    delete[] 이차원포인터[i];-->가로에 할당된 배열을 해제시킨후

}

2.맨 앞부분 해제

    delete[] 이차원포인터;

'언어 > CPP(cpp)' 카테고리의 다른 글

오버라이딩  (0) 2018.02.06
상속  (0) 2018.02.06
const  (0) 2018.02.06
operator overloading(연산자 오버로딩)  (0) 2018.02.05
vector_static변수_static함수  (0) 2018.02.05

const 는 변수를 상수화 하여 사용할때 사용한다.

const형 으로 선언한 클래스는 const 함수만 사용 가능하다.

클래스에서 맴버변수의 변형을 막기 위하여 사용한다.

const <리턴> 클래스명::함수명(매개변수){...}-->리턴값.즉 나의 맴버변수값을 보호!

call by reference나 call by pointer의 경우 외부값을 보호하기 위하여 사용한다.

<리턴> 클래스명 :: 함수명 (const 매개변수)-->매개변수를 보호!

'언어 > CPP(cpp)' 카테고리의 다른 글

상속  (0) 2018.02.06
동적배열과 이차원 동적배열  (0) 2018.02.06
operator overloading(연산자 오버로딩)  (0) 2018.02.05
vector_static변수_static함수  (0) 2018.02.05
클레스  (0) 2018.02.05

vector

array와 달리 한번정한 크기를 바꿀 수 없다.

그러나 vector는 크기를 가변적으로 바꿀 수 있다.

정의는

vector<type> 변수명;

예제

이밖에 여러 맴버 함수가 존재한다.

클래스에서의 static

static 변수는 class 내에서도 맴버변수로 사용 될 수 있다.

그냥 맴버변수는 인스턴스가 생성될때마다 새로 공간이 할당되어지지만, static 맴버변수는 모든 인스턴스에서 동일하다. 또한 공단도 새로 할당되어지지 않는다.

접근지정자 역시 사용가능하며 맴버변수를 선언할때 앞에 static을 붙여주면 된다.

헤더파일에서의 정의

class <클래스명> {
...

<접근 제한자>:
    static <데이터타입> <데이터명>; --->선언은 하되 초기화는 해주지 않는다.!
                                --->클래스내에서 하면 에러가 발생한다.
                                --->클래스 외부에서 전역변수처럼 초기화!
...
}

main이 들어있는 cpp

#include <iostream>

using namespace std;

<데이터 타입> <클래스명>::<static 변수명> = <초기화값>;

int main(){

}

static 에 접근하는 방법

int main(){

    <클레스명>::<static변수명>-->클래스의 함수 쓰듯이 사용한다.

}

static 함수

static 함수 내에서는 static 변수만 사용이 가능하다.

static 함수에서 맴버변수는 사용이 불가능하다.

이는 다른 구간의 지역변수를 사용하는것과 동일한 이치이다.

헤더파일에서 선언

static <return type> 함수명 ();

cpp파일에서의 선언

<return type> <class 명>::<함수명>(){

}

--->cpp파일에서는 일반 함수 선언과 동일하며 앞에 static은 붙지 않는다
--->body에 변수는 static변수만 이용가능하며 맴버변수는 불가능하다.

main에서의 사용

int main(){

    클래스명::함수명();-->객체를 생성하여 사용하지 않고 클래스에서 불러와 사용.

}

'언어 > CPP(cpp)' 카테고리의 다른 글

const  (0) 2018.02.06
operator overloading(연산자 오버로딩)  (0) 2018.02.05
클레스  (0) 2018.02.05
함수 default  (0) 2018.02.05
overloading  (0) 2018.02.05

클래스

클래스란?

c의 구조체에서 확장된 c++에서의 구조체이다.

c의 구조체는 변수에 국한되지만 클래스는 변수 뿐 아니라 함수까지 포함 할 수 있다. 또한 제한자를 통하여 함수나 변수의 접근범위를 제한할 수 있다.(구조체는 public으로 제한자가 정해짐)

우리는 앞서 객체지향에 관한 이야기를 하였다. c++을 객체지향적 언어로 볼 수 있는 이유중 가장큰 부분은 이 클래스 때문이다. 클래스를 이용하여 객체를 찍어낼 수 있다. 즉 클래스는 객체를 만들어주는 틀로 생각하면 된다.

즉 클래스 자체는 완벽한 데이터타입이 되며 모든 데이터 타입 부분에서 사용 가능하다.

접근제한자

위에서 제한자를 이야기하였다. 이는 접근 제한자를 의미한다. 이것은 무엇일까??

종류는 총 세가지로 나뉜다.

1.public

어디에서든 사용이 가능하다. (자기 클래스 뿐아니라 상속된 자식클래스, 클래스 외부 에서 모두 접근가능. 보통 함수를 public으로 한다.) 상속은 뒤에서 보다 자세히 설명하도록 하겠다.

2.protected

자기 자신의 클래스와 상속된 클래스 에서 접근가능

3.private

저기자신의 클래스 내에서만 접근가능. 보통 맴버변수를 private로 선언한다.

클래스 만들기

  • 헤더파일-절때 이렇게 사용하지 않아도 된다. 대게 이렇게 쓴다. 클래스의 정의부이다.

    class <클래스명>{

    public:
           <함수명>(); <--생성자
        ~<함수명>(); <--소멸자
    
    private:
        맴버변수;
    
    public:
        맴버변수에 대한 set과 get함수;
           맴버함수;
    

    }; <---여기 꼭 세미콜론을 붙여주어야한다.

  • .cpp 파일-함수의 정의부

    #include "클래스 정의부"
    
    클래스명::함수명():맴버변수(디폴트값){
    
    }
    
    클래스명::~함수명()::맴버변수(){
    
    }
    
    //set함수는 외부 영역에서 클래스내부의 값을 setting 하여주는 함수이다.(private으로 하였기에 함수를 통하여 내클래스로 내려와 정의하는 방식이다.)
    
    void 클래스명::함수명(<type> 변수명){
    
        맴버변수=변수명;
    
    }
    
    ->대게 이런식으로 한다. 포인터나 클래스가 변수로 들어와 받아야하는경우 deep copy로 해주어야 한다. 이는 뒤에서 설명하도록 하겠다.
    
    //get함수는 외부 영역에 클래스 값을 넘겨주는 것이다.
    
    <내보내줄 데이터 타입> 클래스명::함수명(){
    
        return (내보내줄 맴버변수)
    
    }
    

  • 그리고 메인

  • 컴파일!

deep copy

call by reference나 call by pointer를 통하여 class에서 set을 하는 경우 deep copy를 한다. 그이유는 그냥 대입연산자를 통하여 복사하는 경우 주소가 복사되기에 같은 방향을 가리킨다. 따라서 값을 for문을 통하여 복사해 주도록 하자.

생성자

객체를 생성할때 맴버변수를 초기화해주는 것이다.

    클래스명::함수명():맴버변수(디폴트값){

    }

    또는
        클래스명::함수명(){
        맴버변수 = 디폴트값;
    }

이런식으로 사용하여준다.

예제1.

예제2.

생성자의 오버로당

생성자는 함수와 마찬가지로 매개변수의 리스트와 타입에 따라 다르게 인식하여 오버로딩이 가능하다.

사용 방법은 함수와 동일하게 매개변수의리스나 타입만 바꾸어주면 잘 작용한다.

정의부

main문

결과

복사 생성자

이미 만들어진 클래스의 맴버변수 값을 생성할 클래스의 맴버변수에 대입연산자를 통하여 복사하고 싶을때 사용한다.

메인함수

정의

int main(){

    <클래스명> <새로만들클래스> = <기존클래스>;

    return 0;
}

.cpp함수

<클래스명>(const <클레스명(데이터타입)> &변수명){

    매개변수=변수명.매개변수;

}

결과

소멸자와 deep copy

소멸자는 객체가 소멸될 시 자동으로 호출된다.

보통 동적 배열 할당을 해제하여 주는대에 사용한다.

소멸자의 정의

~클래스명::클래스이름(){
delete[] 동적배열된 맴버변수;
}

그러면 이렇게 한번 생각해보자.

어느 클래스에서 동적배열을 할당한 배열에 set함수를 통하여 외부값을 받았다고 해보자.

이를 대입연산자 = 을 이용하여 대입시 동적배열을한 포인터와 외부포인터가 가리키는 값이 동일하게 된다.

그런데 클래스의 동적배열된 메모리영역은 소멸자를 통하여 해제가 될것이고, 그렇게 된다면 기존에 가리키고 있떤 데이터공간의 메모리 공간이 해제가 된다.

그렇게되면 외부에서 기존에 가리키고 있던 포인터는 오류가 발생한다.

또한 두개의 서로다른 인스턴스가 동일한 공간을 가리키는경우 메모리 해제시 두번째 해제되는것은 해제할것이 없어지게 되어 오류가 발생한다.

따라서 이를 해결하기 위하여 값을 반복문을 통하여 받아주는 deep copy를 실행하여야 한다.

함수의 default

함수의 매개변수를 default로 할수 있다. 즉 초기값을 미리 정해주는 것이다.

이는 선언부에서 정의하여야한다.(not 정의부!)


형식은 <retunrn type><함수명> (매개변수=default값);
이러한 형식이며 예를들어 void function (int i=1);
이러한식이다.

위와같이 잘 됨을 알 수 있다.그런데 main함수에서 보면 매개변수를 앞에서부터 받음을 알 수 있다. 그러니 default값은 뒤에서 부터 선언해주도록 하자.

예를들어 위와같이 할시 input3는 default가 없으므로 오류가 발생한다.

overloading

함수의 이름은 동일하나 매개변수의 길이와 type에 따라 다른 함수로 인식 가능. 이때 return type은 고려하지 않는다.

정의

예를들어 절댓값을 만들어주는 함수 abs의 경우 abs(int) abs(double) abs(float)모두 가능하다. 이는 세개 모두 다른 함수임을 의미한다. 하지만 사용이가능함은 바로 overloaing의 특성을 이용한 것이다.

이때 overloading을 이용시, 프로그래머들은 함수의 body의 내용은 모두 동일하게 해준다고 약속하였다.
보통 함수에서 overloading 하는 경우보다는 연산자를 이용하여 overloading 하는 경우가 많다. 이는 class에 대한 개념을 배운후 연산자 오버로딩(operator overloading)을 통하여 보다 자세히 설명하도록 하겠다.

리턴타입을 다르게 하고 나머지는 동일하게 할시 정의 두번을 했다는 오류가 나온다.

매개변수를 한개는 int, 한개는 double로 했을때의 결과

c++이란?

객체 지향성 언어이다.(절차지향도 가능함)

객체란? 상태와 행동을 갖는 모든것을 의미. 프로그램에서는 상태는 변수를통하여, 행동은 메소드를 통하여 나타낸다.

  • 절차 지향 언어

입력을 받아 순차적으로 처리되며 유기적으로 연결되어 있어야함. 객체지향에 비하여 속도가 빠

르다.

  • 객체 지향 언어

데이터와 절차를 하나의 묶음으로 정리하여 서로 다른 묶음으로 구성하여 프로그램을 구성함

특징으로는 캡슐화, 상속(heritance), 다형성(overloading)이 있다. 뒤에서 설명하도록 하겠다.

객체지향의 장점은 코드의 재사용이 쉬우며 다형성과 namespace의 사용으로 변수사용에 비교적 자유롭다. (namespace도 뒤에서 사용하도록 하겠다.)

입출력 개체 cin, cout

c++라이브러리에 있는 헤더파일로 input,output객체들의 정의부가 존재한다.

코드를 통해 좀더 자세하게 설명하도록 하겠다.

출력 객체 cout

cascading

cout << <원하는출력>에서

cout은 객체이고 << 을 함수로 사용한다.

함수 << 의 역할은 cout과 <원하는출력>을 각각 매개변수를 받아 <원하는출력> 을 cout객체로 넘겨준다. 그러면 cout은 이를 출력한다. 그리고 cout을 다시 return으로 되돌려주어 사용이 가능하도록 해주는것이다.

ex)
cout << 1 << "abcd";는 실제로
cout << 1 을 시행한후
cout << "abcd"를 하는것이다.
이를 캐스캐이딩이라 한다.

우분투에서의 컴파일

입력 객체 cin

cout,cin의 최대장점은 변수,상수,문자,문자열등 어떤 표현이든 output이 된다. 즉 <<(cout,int),<<(cout,double),<<(cout,string)이 정의되어 있는것이다.

cout 출력 포메이팅

flag변수를 건드림으로써 출력 포메이팅을 정할 수 있다.

flag는 1비트로써 true false를 정한다.

출력 포메이팅을 보면

cout.setf(ios::fixed);

cout.setf(ios::showpoint);

cout.precision(원하는 자릿수);

이런식으로 진행을 하는데

cout.setf(ios::fixed); ->부동 소수점을 사용하겠다는 비트를 1로 올려줌

cout.setf(ios::showpoint); ->부동 소수점을 show.즉 화면을 통해 보겠다를 1로 올려줌

cout.precision(원하는 자릿수); ->원하는 자릿수를 지정해줌.

'언어 > CPP(cpp)' 카테고리의 다른 글

overloading  (0) 2018.02.05
call by reference vs call by value vs call by pointer_g++로 헤더파일_cpp파일 동시 컴파일  (0) 2018.02.03
github_cpp  (0) 2017.12.26
char string  (0) 2017.12.25
static,vector(벡터)  (0) 2017.12.25

+ Recent posts