다형성의 기본개념

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

 

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


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

하지만 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;
}

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;
}

상속받은 함수를 오버라이딩하기

상속을 사용하는 일반적인 경우엔

상속을 해주는 부모클래스와 상속을 받는 자식클래스는
보통 기능차이가 많지않을 수 있다.

이때 함수오버라이딩을 유용하게 사용할수 있다.

함수 오버라이딩할때 부모클래스의 함수를 사용하고 싶다면 부모클래스이름은 선언한다.

Base::Print();


다형성에서 사용된다.

<< operator 를 사용하고 싶으면 static_cast해서 사용한다.

out << static_cast<Base>(b) << endl;

 

#include <iostream>

using namespace std;

class Base {
protected:
	int m_i;

public:
	Base(int a)
		: m_i(a)
	{

	}

	void Print() {
		cout << "I'm  Base" << endl;
	}

	friend std::ostream & operator << (std::ostream & out, const Base &b) {
		out << "Base opertator";
		return out;
	}
};

class Derived : public Base {
public:
	double m_d;

	Derived(int a)
		:Base(a) {

	}

	void Print() {
		Base::Print();
		cout << "I'm  Derived" << endl;
	}

	friend std::ostream & operator << (std::ostream & out, const Derived &b) {
		out << static_cast<Base>(b) << endl;
		out << "Derived opertator";
		return out;
	}
};

int main()
{
	Base b(5);
	Derived d(2);

	b.Print();
	d.Print();
	cout << b << endl;
	cout << d << endl;
	return 0;
}

상속과 접근지정자

클래스에서 접근지정자로 접근권한을 제한할 수 있다.
상속도 마찬가지로 접근지정자로 제어할 수 있다.

protected는 외부에선 접근 불가능하지만 자식클래스에서 접근가능하다.

유도된 클래스(자식클래스)에 새로운 기능 추가할때
protected를 사용하면 private 변수일때 public에 getValue()를 만들어 사용하지않고 퍼포먼스를 향상시킬 수 있다.

 

#include <iostream>
using namespace std;
class Base {
protected:
	int m_public;

public:
	Base(const int & a) 
	:m_public(a){

	}
};

class Derived : public Base
{
public:
	Derived(const int & a) 
	:Base(a){
	
	}

	void setValue(int value) {
		Base::m_public + value;
	}
};
int main()
{

	return 0;
}


다중상속일때 단계가 높은 부모클래스에 접근하지 못하게할때 사용한다.

즉, private 으로 상속하면 다중상속일때 하하위 클래스가 직접접근하지 못하게한다.

 

#include <iostream>

using namespace std;

class Base {
public:
	int m_public;

	int funPublic() {
		return 0;
	}
protected:
	int m_protected;
	int funProtected() {
		return 0;
	}
private:
	int m_private;
};

class Derived : public Base
{
public:
	Derived() {
		m_public = 123;
		m_protected = 123;
		//m_private = 123;
		funPublic();
		funProtected();
	}
};

class Derived2 : protected Base
{
public:
	int a;
	Derived2() {
		m_public = 123;
		m_protected = 123;
		//m_private = 123;
		a = funPublic();
		a = funProtected();
	}
protected:
	int a2 = 0;
};

class Derived3 : private Base
{
public:
	int a;

	Derived3() {
		m_public = 123;
		m_protected = 123;
		//m_private = 123;
		a = funPublic();
		a = funProtected();
	}

};

class GrandChild : public Derived3 {
public:
	GrandChild() {
		//m_public; 불가능하다
		cout << a << endl;
	}
};

int main()
{
	Derived der;

	der.m_public = 123;
	//base.m_protected = 123;
	//base.m_private = 123;
	
	//protected 상속
	Derived2 der2;
	//der.m_public = 123;

	//private 상속
	Derived3 der3;
	//der.m_public = 123;


	return 0;
}

+ Recent posts