C++ 생성자 안에서 멤버변수 값을 설정할 때 유효성 검사에 관하여 질문 드립니다.

yserzero의 이미지

다음과 같은 코드가 있습니다.

#include <iostream>
using std::cout;
using std::endl;
class A {
private:
	int a;
	int b;
public:
	A(int a, int b) {
		if (a < 0) {
			std::cout<<"a값 입력 오류"<<std::endl;
			return;
		}
		this->a = a;
		this->b = b;
	}
	int getA() {
	  return a;
	}
	int getB() {
	  return b;
	}
};
 
int main() {
  	A a(-1, 0);
	std::cout<<a.getA()<<std::endl;
	std::cout<<a.getB()<<std::endl;
 
	return 0;
}

클래스 A 객체 생성하여 생성자에 멤버변수 값을 설정해 주는데,
위와 같이 생성자 안에서 유효성 검사하고 return을 하는게 올바른 것인가요?
일단 컴파일도 잘 되고 제가 원하는 결과를 보여주긴 합니다만,
전문가의 눈으로 봤을 때 어떤 문제라던가 개선점이 있는지가 궁금합니다.
많은 답변 부탁드립니다.

ifree의 이미지

별 문제는 없는 듯.

planetarium의 이미지

본론과 관계 없습니다만
using std::cout; 이라는 구문은
std::cout << ...; 을
cout << ...; 로 줄여 쓰기 위한 구문입니다.
따라서 using 식별자를 쓰셨으면
본문 중에 굳이 std::cout 이라고 지정해 줄 필요가 없습니다.
지금처럼 cout 이나 endl 이 많이 쓰이는 경우
std:: 부분을 떼어주는 게 가독성이 훨씬 좋아질 겁니다.

drinkme의 이미지

이러한 방법의 문제는
생성자를 호출한 ... 그러니까, 초기값을 부여하여, new 연산자 등을 호출한... 측에서
이놈이 정상적으로 호출되었는지, (초기화 되었는지) 아닌지를
알 수 있는 방법이 모호하다는 것입니다.

안좋은 방법이죠.
예외를 던지거나 하는 방법 등을 찾는게 좋을 듯 합니다.

레모네이드의 이미지

생성자의 파라미터 입력이 여기서는 상수로 되어 있는데, 불특정의 변수도 올수 있겠져...
예외를 검출하는 방법을 쓰는게 좋을듯..
콘솔에서만 사용하는 목적이라면 위의 코드가 별탈은 없겠지만...그렇지 않다면 예외검출 함수를 별도로 만드는게 좋겠죠..
어차피 생성자이니깐 멤버의 초기값은 쓰레기이든 입력값이 그대로 넣는 무관할 꺼구요...
생성자의 경우 성공 실패를 리턴하는 방법이 파라미터를 이용하거나...try~catch

저의 경우엔 try~catch 의 예외처리 방법은 별로 좋아하지 않기에 ... 아래 방법처럼 하고...

#include <iostream>
 
using std::cout;
using std::endl;
 
class A
{
private:
	int a;
	int b;
public:
	A(int a, int b)
	{
		this->a = a;
		this->b = b;
	}
 
	bool check_create()
	{
		return a >= 0;
	}
 
	int getA()
	{
		return a;
	}
 
	int getB()
	{
		return b;
	}
};
 
int main()
{
	A a(-1, 0);
	if( a.check_create() )
	{
		cout << a.getA() << endl;
		cout << a.getB() << endl;
	}
	else
	{
		cout << "a값 입력 오류" << endl;
	}
 
	return 0;
}

또 다른 방법으로는 생성자를 다음과 같이 작성하는거..

	A(bool& creation, int a, int b)
	{
		if( a < 0)
		{
			creation = false;
		}
		else
		{
			creation = true;
			this->a = a;
			this->b = b;
		}
	}

또는

#include <iostream>
 
using std::cout;
using std::endl;
 
class except_class_create {};
 
class A
{
private:
	int a;
	int b;
public:
	A(int a, int b) throw ( except_class_create )
	{
		if( a < 0) throw except_class_create();
		this->a = a;
		this->b = b;
	}
 
	int getA()
	{
		return a;
	}
 
	int getB()
	{
		return b;
	}
};
 
int main()
{
	try
	{
		A a(-1, 0);
		cout << a.getA() << endl;
		cout << a.getB() << endl;
	}
	catch(class except_class_create)
	{
		cout << "a값 입력 오류" << endl;
	}
 
	return 0;
}

이런게 있을수 있는데....
try~catch사용이 많으면 개발자가 코드의 흐름을 이해 못할 경우도 있고...try~catch는 개발할때 철처하게 따져서 작성해야되기 땜에
실수하면 코드 복잡해지면 버그 잡기 힘듭니다...ㅋㅋ..

yserzero의 이미지

답변 주신 분들 감사드립니다.
많은 공부가 되었습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.