2010-06-01 8 views
4

다소 혼란 스러울 수도 있습니다. 기본적으로, 함수 새로운 CCard 변수를 생성하고 호출자에게 돌려다시 변수 초기화

CCard newCard() 
{ 
    /* Used to store the string variables intermittantly */ 
    std::stringstream ssPIN, ssBN; 
    int picker1, picker2; 
    int pin, bankNum; 

    /* Choose 5 random variables, store them in stream */ 
    for(int loop = 0; loop < 5; ++loop) 
    { 
     picker1 = rand() % 8 + 1; 
     picker2 = rand() % 8 + 1; 
     ssPIN << picker1; 
     ssBN << picker2; 
    } 
    /* Convert them */ 
    ssPIN >> pin; 
    ssBN >> bankNum; 

    CCard card(pin, bankNum); 
    return card; 
} 

선생님은이 일을하는 것은 OOP 원칙의 위반이고에가 나에게 조언

CCard card = newCard();

수업에 참여하십시오. 그는이 방법을 생성자로 사용하라고했습니다. 내가 한 일 :

CCard::CCard() 
{ 
    m_Sperre = false; 
    m_Guthaben = rand() % 1000; 

    /* Work */ 

    /* Convert them */ 
    ssPIN >> m_Geheimzahl; 
    ssBN >> m_Nummer; 
} 

m_의 모든 변수는 멤버 변수입니다. 나는이 프로그램의 시작 부분에 카드 일반적으로

CCard card();

를 초기화 할 때, 생성자 작동합니다. 그러나, 나는 또한 새로운 카드를 만들어서 그것을 사용자에게 돌려 주어야하는 함수를 가지고 있는데,이 함수는 이제 깨졌습니다.

원래 명령 : card = newCard();은 더 이상 사용할 수 없으며 card = new CCard();은 작동하지 않습니다. 다른 옵션은 무엇입니까? 생성자를 사용하는 느낌이 들지 않습니다. 클래스 메소드 newCard를 작성해야합니다.하지만 교사가 원했던 방식으로 어떻게 든 할 수 있는지 확인하고 싶습니다.

이것은 나를 위해 많은 두통을 만들어냅니다. 나는 선생님에게 이것이 어리석은 생각이고 모든 것이 OOP에서 분류되어야한다고 말했습니다. 그는 이후 Java 또는 C#이 클래스 외부의 코드를 허용하지 않는다고 말했고 약간 놀라운 것으로 들립니다. C++에서이 작업을 수행 할 수 있는지, 특히 템플릿 함수가 있거나 일반 알고리즘이있는 경우에는 특히 그렇습니다. 클래스에 강제로 넣지 않았다면 이것이 C++의 OOP에 나쁜 코드가된다는 것이 사실입니까?

편집 : 나는 그들의 도움이되는 답변을 모두에게 감사의 말씀을

! 그러나 나는 그 질문에 대한 나의 말씨가 조금 엉망이되어서 사람들이 내가 무엇을 찾고 있는지 이해하지 못한다고 생각한다.

할 일 아니요 CCard 유형의 다른 멤버를 초기화하려고합니다. 초기화하고 싶습니다

한 번 다음에 교사가 말한대로 생성자를 통해 card 개의 새 값을 제공하십시오. 새로운 CCard 객체를 만들고 싶지 않습니다. 동일한 변수를 새로운 값으로 다시 사용하십시오.

이것이 내가 생성자와 함께 작동하지 않는다고 말한 이유입니다. 그래서 초기화 된 변수 card을 가져 와서 생성자를 다시 호출해야하는 함수가 있습니다 ("무엇?"가 교사에게 말한 것입니다). 그런 다음 새 값을 지정합니다.

예제 코드 :

void foo() 
{ 
    /* Initialize card with constructor */ 
    CCard card; 
    /* Give it new values through the constructor AGAIN... */ 
    card; 
} 

이 실제 질문입니다.나는 모두의 xD를 혼동하는 경우 미안 해요

+2

"OOP로 모든 것을 분류 할 필요는 없지만 그는 Java 나 C#이 클래스 외부에서 코드를 허용하지 않는다고 나에게 이야기 해주었습니다. 너는 완전하고 선생은 바보 야. C++은 OOP 언어가 아니며 OOP만이 프로그래밍 패러다임이 아닙니다. 사실, 현대 C++ 디자인은 멤버 함수보다 자유 함수를 선호해야한다고 규정합니다! 선생님은 잘못된 것을 이유로 생성자로 이동해야 할 수도 있습니다. OOP가되기 위해 물건을 OOP로 만들지 말고, 그것이 의미가있는 경우 OOP로 만들고, 그렇지 않은 경우 OOP로 만듭니다. – GManNickG

+2

그건 말하자면, 당신이하는 일에 달려 있습니다. 카드에 기본 상태가 있으면 기본 생성자가 그 것입니다. 그렇지 않으면 생성자에 속하지 않습니다. 그건 그렇고, 당신은'return CCard (pin, bankNum);'을 할 수 있고, 당신은 디폴트 생성자를 "호출"하지 않고 자동적으로 끝난다. (그 점은 디폴트 값으로 구성되어있다.) 새로운 카드'CCard someCard;를 만들고 그냥'someCard'를 디폴트로 만드십시오. – GManNickG

+0

@GMan : 나는이 포괄적 인 성명서에 예외를 두었다 : "이것을하는 것은 OOP 원칙을 위반하는 것이다"; 그러나 "this"를 "생성자 외부에서 필요한 객체 상태 초기화 수행"을 의미하는 것으로 받아 들인다면 좋은 객체 설계를 위반하는 것에 동의 할 것입니다. –

답변

7

오해가 있기 때문에 기본 포인터 만 사용하십시오.

이 개체는 CCard 개체를 초기화하지 않습니다. cardCCard을 반환하고 매개 변수를 취하지 않는 함수로 선언합니다.

CCard card(); 

CCard 개체를 구성하려면이 작업을 수행하십시오.

CCard card; 

생성자가 호출되고 card을 올바르게 초기화해야합니다.

표현 new CCard() 동적으로 CCard 객체와 "반환"당신이 다음 delete에 필요한 것 CCard 객체에 포인터을 만듭니다. 먼저 로컬 객체를 사용하여 성공적으로 만들고 이해할 때까지이 방법을 사용하지 않는 것이 좋습니다. 응답

편집은 편집 적 객체 '- 구조 다시'할 수 있도록 생성자 만 개체의 일생에 한 번 호출 할 수 있습니다

에 의문을 제기합니다. 클래스가 할당 할 경우,하지만, 일반적으로는 디폴트의 값이 일시적으로 구성 지정할 수 있습니다

card = CCard(); 
+1

[가장 짜증나는 구문 분석]에 대한 좋은 질문입니다 (http://stackoverflow.com/questions/2318650/is-no-parentheses-on-ac-constructor-with-no-arguments-a-language-standard). –

+0

@Charles Bailey : 입력 해 주셔서 감사합니다.하지만 컴파일러에서 유효한 기본 생성자가 없다는 것을 알려줍니다. 카드 및 카드 정리에 큰 감사드립니다. 그건 내 부분에 대한 큰 오해 였어! – IAE

+1

@Soul : 비공개로 설정 한 것 같습니다. ('class'는 기본적으로 접근성을 private으로 기본 설정합니다.)'class foo {public : foo() {}};' – GManNickG

1

나 C++에 새로운 해요,하지만 난 당신이 기능에서 개체를 반환하는 복사 생성자를해야 할 수도 있습니다 생각 :

CCard::CCard (const CCard &rhs) 
    : m_Gehiemzahl(rhs.m_Geheimzahl) // and so on for each member variable 
{ 
} 

잊지 마세요 은을 추가 클래스 선언의 프로토 타입.

+1

동적 생성자가 아닌 경우 복사 생성자가 자동으로 제공되고 제대로 작동합니다. – Nikko

+1

당신은, 컴파일러는 기본 복사 생성자를 생성 할 것이고, 그의 CCard는 기본 요소를 사용하는 것처럼 보이기 때문에 (기본값은 각 멤버 필드에 대한 기본값은'this-> foo = other-> foo; '입니다) –

+0

@ all : Cool, thanks, knowing good. – dreamlax

3
CCard card; 

기본 생성자를 사용하는 방법입니다.

선생님이 틀렸어. C++에서는 무료 함수를 사용하여 기능을 매우 열정적으로 확장합니다.

newCard를 할 필요가없는 특별한 요구 사항을 제외하고는 이런 식의 의미이므로 생성자를 사용하는 것이 좋습니다. 불필요한 복사본을 생성합니다.


"새로운"포인터 예약, 그래서 당신은 같은 것을 사용해야한다 :

CCard * card = new CCard(); 

을 그리고 당신은 그들을 명시 적으로 delete에 있습니다. 그러나 포인터는 필요한 경우에만 사용해야하며 가능한 경우 '원시'가 아니라 스마트합니다.당신의 편집 할


을 (부스트 :: shared_ptr의 같은 스마트 포인터 참조)

당신은 당신의 CCard 새 값을 사용하여 제공 할 수 있습니다

:

-)와 같은 CCard하는 방법 :

에게
card.newValues(); 

생성자는 "newValues ​​()"를 호출하여 중복되는 것을 방지 할 수도 있습니다.

-)는 기준 파라미터로 CCard 걸리는 프리 기능 (또는 다른 클래스의 멤버)

void newValues(CCard & card) { /* set new values */ }; 

newValues(card); 

- 직통) 접근 세트와 어쩌면

card.set(/*values*/); 

(set/get) 클래스에 대한 의미가 있다면.

자신에게 질문해야 할 질문은 접근자를 사용하여 클래스 내부를 변경할지 아니면 클래스 내부의 값만 변경할지 결정하는 것입니다.

-) 당신이 정말로 다시 생성자를 호출 할 경우, 당신은 복사 할 수 있습니다 :

CCard c; 
c = CCard(); 

을하지만 그것은 단지 새로운 CCard을 만드는 것과 같습니다.

+0

'std :: auto_ptr' /'std :: unique_ptr'는'shared_ptr'보다 시작하는 것이 더 나을 것 같습니다. –

+0

예 초보자를위한 문제는 std :: auto_ptr이 컨테이너 안에 사용되어서는 안된다는 것을 설명하는 것입니다. – Nikko

+0

제 편집에 응답 해 주셔서 감사합니다 ^^ 제 생각에 그것은 단지 성가신 일입니다. Oof, 선생님. 그 점을 분명히 해줘서 고마워! – IAE

0

선생님이하려는 것은 새로운 물건이 필요 없다는 것입니다. 대신 현재 갖고있는 객체와 상호 작용/조작 할 수있는 방법을 제공해야합니다. 객체를 재구성하거나 객체의 내부 상태를 변경하기 만하면됩니다.

물론 가변적 인 상태가 버그의 큰 원인이라고 여겨지는 "기능적 언어 원리"에 대한 큰 변화가 있습니다. 그러나 가변 국가는 그 자체로 나쁘지 않습니다. 객체의 내부 상태를 변경하는 것이 항상 명확하지는 않다는 사실입니다. 당신은 그것을 명백하게하고 싶습니다.