가상함수와 다형성

다형성은 상속구조와 virtual을 사용한다.

virtual을 붙인 함수는 가상함수라고 부른다.

A,B,C,D 4가지 클래스를 생성하고 상속을 해보았다.

A의 포인터,Reference를 사용하며 A클래스의 메소드에 virtual을 사용하게 되면

자식클래스들은 모두 영향을 받는다.

즉, 가장 상위클래스의 virtual이 되면 밑에 클래스 모든 메소드도 virtual로 인식되게 된다.

상위클래스에만 있어도 되지만 형식적으로 자식클래스에도 virtual을 사용해놓는다.

오버라이딩한걸 인식하기 위해서 이다.

virtual 키워드는 스택처럼 차곡차곡 쌓는게 아닌 테이블을 찾는 과정이다.

찾아가는 과정이 있기에 속도가 느리다.

 

#include <iostream>
#include <string>

using namespace std;
class A
{
public:
	virtual void print() {
		cout << "A" << endl;
	}
};

class B : public A
{
public:
	void print() {
		cout << "B" << endl;
	}
};

class C : public B
{
public:
	void print() {
		cout << "C" << endl;
	}
};
class D : public C
{
public:
	void print() {
		cout << "D" << endl;
	}
};

int main()
{
	A a;
	B b;
	C c;
	D d;

	//포인터도 사용가능
	//가장 상위클래스에 virtual이 선언되어 있으면 모두 영향 받는다.
	A &ref = c;
	ref.print();

	return 0; 
}

'개발 소발 > 개발 C++(기초)' 카테고리의 다른 글

c++ 가상소멸자  (0) 2019.09.23
c++ override,final,공변 반환값  (0) 2019.09.23
c++ 다형성의 기본개념  (0) 2019.09.23
c++ 상속받은 함수를 오버라이딩하기  (0) 2019.08.30
c++ 상속과 접근지정자  (0) 2019.08.30

다형성의 기본개념

자식클래스의 객체에 부모 클래스의 포인터를 사용한다면?

 

부모클래스 *포인터 = 자식클래스;


위처럼 하면 부모클래스의 메소드가 실행된다. 

하지만 virtual을 메소드에 붙여주면 자식 메소드가 실행되게 된다.

	virtual void speak() const
	{
		cout << m_name << " ??? " << endl; 
	}


자식클래스에 메소드가 없으면 부모클래스가 실행된다.

이걸 다형성이라고 부른다.

 

#include <iostream>
#include <string>

using namespace std;

class Animal
{
protected:
	string m_name;

public:
	Animal(string name)
		: m_name(name) {

	}

	string getName() { return m_name; }

	virtual void speak() const
	{
		cout << m_name << " ??? " << endl; 
	}
};

class Cat :public Animal 
{
public:
	Cat(string name)
		:Animal(name) {

	}

	void speak() const
	{
		cout << m_name << " Meow " << endl;
	}
};


class Dog :public Animal
{
public:
	Dog(string name)
		:Animal(name) {

	}

	void speak() const
	{
		cout << m_name << " Woof " << endl;
	}
};
int main() {

	Animal a("Animal");
	Dog d("Dog");
	Cat c("Cat");

	//자식클래스를 부모클래스의 포인터로 캐스팅해서 사용하면
	//자신이 부모클래스인줄 알고 작동한다.
	a.speak();
	d.speak();
	c.speak();

	Animal *a1 = &d;
	Animal *a2 = &c;


	//활용하는 경우
	Cat cats[] = { Cat("cat1"),Cat("cat2"), Cat("cat3"), Cat("cat4"), Cat("cat5") };
	Dog dogs[] = { Dog("dog1"), Dog("dog2") };
	//위에껄 다 확인해볼려면 for문을 사용해야한다.

	Animal *my_animals[] = { &cats[0],&cats[1], &cats[2], &cats[3], &cats[4], &dogs[0], &dogs[1] };

	//부모클래스의 메소드가 실행된다.
	//virtual 을 붙이면 자식클래스인것처럼 실행한다.
	//이런 성질을 다형성이라고 한다.
	for (int i = 0; i < 7; i++)
		my_animals[i]->speak();


	return 0;
}
  • 생산성 향상을 위해선 IDE를 잘 활용해야한다.

    ToolBox

    JetBrains 홈페이지 접속
    Tool Box App을 다운받아서 여러 IDE 설치를 권장한다.

    Intellij IDEA Ultimate 는 유료지만 자바스크립트,스프링,서블릿을 사용할 수 있다.

    프로젝트 생성하기

    GroupID : 프로젝트 그룹을 이야기한다.(스프링)
    ArtifactID : 프로젝트 그룹의 하위 모듈(스프링 시큐리티,MVC)

    메인메소드 생성하고 실행하기

    파일생성 : command + n ,Alt+insert
    메인메소드 : psvm
    System.out.println() : sout
    실행환경 실행 현재 : 맥 Ctrl + Shift + R 윈도우 Ctrl + Shift + f10
    실행환경 실행 이전 : 맥 Ctrl + R  윈도우 Shift + f10

    라인수정하기

    1.라인 복제하기 

맥 command +d 윈도우 Ctrl + d


2.라인 삭제하기 

맥 command +d 윈도우 Ctrl + y


3.문자열 라인 합치기 

맥,윈도우 Ctrl + Shift + j


4.라인 단위 옮기기 
구문 (메소드 안) 

맥 command + shift + 방향키 윈도우 ctrl + shift + 방향키
라인이동  

맥 Option + Shift + 방향키  윈도우 Shift + Alt + 방향키

 

5.Element 단위로 옮기기
구문 (메소드 안) 

맥 option + command + shift + 방향키 윈도우 alt + ctrl + shift + 방향키

코드 즉시보기

1.인자값 즉시 보기
맥 command + p 윈도우 ctrl + p


2.코드 구현부 즉시 보기(직접 안찾아 가도 됌)
맥 option + space 윈도우 Shift + Ctrl + i


3.Doc 즉시 보기
맥 F1 윈도우 ctrl +q

N개의 자연수가 입력되면 각 자연수를 뒤집은 후 그 뒤집은 수가 소수이면 그 수를 출력하는 프로그램을 작성해보자.

예를 들어 32를 뒤집으면 23이고, 23은 소수이다. 그러면 23을 출력 한다. 단 910를 뒤집으면 19로 숫자화 해야 한다. 뒤집는 함수인 int reverse(int x) 와 소수인지를 확인하는 함수 bool isPrime(int x)를 반드시 작성하여 프로그래밍 한다.

 

힌트 : 숫자 뒤집는 방법생각하기

소수란? 나눠지는 수가 없는 숫자를 말한다.

 

#include <stdio.h>

int reverse(int x){
	int res = 0;
	while(x>0){
		int tmp = x%10;
		res = res*10 +tmp;
		x= x/10;
	}
	return res;
}

bool isPrime(int x){
	int i;
	bool flag = true;
	
	if(x ==1){
		return false;	
	}
	
	for(i = 2; i < x; i++){
		if(x%i ==0){
			flag=false;
			break;
		}
	}
	
	return flag;
}

int main(int argc, char** argv) {
	//freopen("input.txt", "rt", stdin);
	int n, num, i, tmp;
	scanf("%d",&n);
	for(i = 1; i<=n;i++){
		scanf("%d",&num);
		tmp = reverse(num);
		if(isPrime(tmp)){
			printf("%d ", tmp);
		}
	}
	return 0;
}

N개의 자연수가 입력되면 각 자연수의 자릿수의 합을 구하고,

그 합이 최대인 자연수를 출력 하는 프로그램을 작성해보자.

각 자연수의 자릿수의 합을 구하는 함수를 int digit_sum(int x)로 작성하자.

 

입력 값 txt파일

맨처음숫자 3은 데이터의 수를 표현해준다.

3
125 15232 97

 

힌트 : 버퍼에는 줄바꿈 띄어쓰기 기준으로 들어간다.

자릿수의 합을 구하는 방법을 한번 생각해보자.

 

#include <stdio.h>

using namespace std;

int digit_sum(int x){
	int sum = 0, tmp;
	while(x>0){
		tmp = x%10;
		sum=sum+tmp;
		x=x/10;
	}
	return sum;
}

int main(int argc, char** argv) {
	freopen("input.txt", "rt", stdin);
	int n, num, i, sum, max = -2147000000, res;

	scanf("%d",&n);
	for(int i = 0; i <n; i++){
		scanf("%d",&num);	
		sum = digit_sum(num);
		if(sum > max){
			max = sum;
			res = num;	
		}
	
	}
	
	printf("%d\n",res);
	
	return 0;
}

 

 

 

괄호가 입력되면 올바른 괄호이면 “YES", 올바르지 않으면 ”NO"를 출력한다.

 

()의 법칙을 생각하자. )가 먼저 나올수 없고 )의 숫자가 더 많을 수 없다.

미리 머리속에 그려보자.

 

힌트 : 숫자를 기준으로 생각하자.

법칙을 생각해보자.

 

#include <stdio.h>

using namespace std;

int main(int argc, char** argv) {
	//freopen("input.txt", "rt", stdin);
	char a[30];
	gets(a);
	
	int  p = 0;
	int  p2 = 0;
	bool b = true;
	for (int i = 0; a[i] != '\0'; i++) {
	
		if(a[i]==40){
			p++;
		}else if(a[i]==41){
			p--;
		}
		
		if(p < 0){
			break;
		}
	}
	
	if(p  == 0){
		printf("%s","YES");
	}else{
		printf("%s","NO");
	}
	return 0;
}
#include <stdio.h>

using namespace std;

int main(int argc, char** argv) {
	freopen("input.txt", "rt", stdin);
	char a[101],b[101];
	gets(a);
	
	int  p = 0;
	for (int i = 0; a[i] != '\0'; i++) {
		//printf("%d\n", a[i]);
		if (a[i] != 32) {
			if (a[i] >= 65 && a[i] <= 90) {
				//printf("%c", a[i] + 32);
				b[p++] = a[i]+32;
			}
			else if(a[i] >= 97 && a[i] <= 122){
				//printf("%c", a[i]);
				b[p++] = a[i];
			}
		}
	}
	
	b[p] = '\0';
	printf("%s",b);	
	return 0;
}

영어단어가 뛰어쓰기와 대소문자가 혼합되어 표현된다.

뛰어쓰기를 제거하고 소문자로 단어를 출력해보자.

 

1.gets로 문자열을 받아온다.(scanf는 뛰어쓰기에서 멈춘다.)

2.문자열을 확인후 뛰어쓰기는 거른다.

3.대문자는 소문자로 변경한다.

 

힌트: 대문자의 아스키코드 65-90이다.

 

 

문자와 숫자가 섞여있는 문자열이 주어지면 그 중 숫자만 추출하여

그 순서대로 자연수를 만 듭니다.

만들어진 자연수와 그 자연수의 약수 개수를 출력합니다.

 

1.문자열을 입력받거나 읽어온다.

2.문자열에서 숫자만 추출한다.

3.추출된 숫자의 약수를 구한다.

 

힌트: 0~9는 아스키코드 48~57이다.

숫자가 더해질때마다 십의 자리가 증가한다.

 

#include <stdio.h>

using namespace std;

int main(int argc, char** argv) {
	//freopen("input.txt", "rt", stdin);
	char a[100];
	scanf("%s", &a);

	int res = 0, cnt=0;

	for(int i = 0; a[i] !='\0'; i++){
		if(a[i] >= 48 && a[i] <= 57){
			res = res*10+(a[i]-48);
		}
	}
	
	printf("%d\n",res);
	for(int i = 1; i <= res; i++){
		if(res%i == 0){
			cnt ++;
		}
	}
	printf("%d\n",cnt);
	return 0;
}

자연수 N이 주어지면 자연수 N의 진약수의 합을 수식과 함께 출력하는 프로그램을 작성하기.

 

진약수란? 특정숫자를 나누었을때 나머지가 0이 되는 숫자를 말한다.

 

1. N값을 입력받는다.

2. 1부터 N의 진약수를 알아보고 출력한다.

1 + x + x + x + x = x 형식으로 출력하기

 

힌트 : 1은 무조건 진약수이므로 미리 출력해도 된다.

 

#include <iostream>

using namespace std;

int main(int argc, char** argv) {
	int n, i = 2,sum = 1;
	cin >> n;

	cout << "1";

	for (i; i < n; i++) {
		if(n%i == 0){
			cout << " + "<<i ;
			sum += i;
		}
		
	}
	cout << " = "<<sum;
	return 0;
}

자연수 N이 입력되면 1부터 N까지의 수 중 M의 배수합을 출력하는 프로그램을 작성한다.

 

N,M을 입력받고 1~N까지 숫자중에 M의 배수들의 합을 구해보자.

 

기초적인 문제 N,M을 입력받는 코드를 작성한다.

1부터 N까지 반복문을 작성하고 그안에 M의 배수를 확인하는 조건문을 작성한다.

조건에 맞는 수를 sum변수에 넣어준다.

#include <iostream>

using namespace std;

int main(int argc, char** argv) {
	int n, m, i = 0, sum = 0;
	cin >> n;
	cin >> m;

	for (i; i <= n; i++) {
		if (i%m == 0) {
			sum += i;
		}
	}
	cout << sum;
	return 0;
}

+ Recent posts