[C++] 파일분할 클래스 상속, 그리고 vtable 오류 질문드립니다

kimhyuns55의 이미지

shape.h

#ifndef __SHAPE_H__
#define __SHAPE_H__
 
class CShape {
protected:
        int x, y;
public:
        CShape(int a, int b) : x(a), y(b) {}
        void Move(int a, int b) {x += a; y += b;}
        virtual void Print() = 0;
};
 
#endif

rect.h
#include "shape.h"
#ifndef __RECT_H__
#define __RECT_H__
 
class CRect : public CShape {
private:
        int Garo, Sero;
public:
        CRect(int a, int b, int g, int s);
        double GetArea();
        virtual void Print();
};
 
#endif

rect.cpp
#include "shape.h"
#include <iostream>
#include "rect.h"
using namespace std;
 
CRect::CRect(int a, int b, int g, int s) : CShape(a, b), Garo(g), Sero(s) {}
double CRect::GetArea() {return (Garo* Sero);}
void Print() {cout << "test" << endl;}

circle.h
#include "shape.h"
#ifndef __CIRCLE_H__
#define __CIRCLE_H__
 
class CCircle : public CShape{
private:
        double Radius;
public:
        CCircle(int a, int b, double r);
        double GetArea();
        void Print();
};
 
#endif

circle.cpp
#include "shape.h"
#include "circle.h"
#include <iostream>
using namespace std;
 
CCircle::CCircle(int a, int b, double r) : CShape(a, b), Radius(r) {}
double CCircle::GetArea() { return (3.14 * Radius * Radius);}
void Print() {cout<< "testc" <<endl;}

main.cpp
#include <iostream>
using namespace std;
#include "shape.h"
#include "circle.h"
#include "rect.h"
 
ostream& operator<< (ostream &out, CShape &Po) {
        Po.Print();
}
int main() {
        CCircle Cir(1, 1, 1);
        CRect Rect(2, 2, 2, 2);
        CShape *pSpe;
 
        pSpe = &Cir;
        cout << *pSpe;
 
        pSpe = &Rect;
        cout << *pSpe;
 
        return 0;
}

간단히 설명드리자면, rect 와 circle의 면적을 출력하기 위해서 shape클래스의 Print 함수를 가상함수로 설정해본 코드입니다

제 기대와는 다르게 여러부분에서 오류가 발생하더군요 ㅠ

아래가 그 리스트입니다

/tmp/cckeSZdQ.o: In function `Print()':
circle.cpp:(.text+0x70): multiple definition of `Print()'
/tmp/ccmv69yx.o:rect.cpp:(.text+0x6d): first defined here
/tmp/ccmv69yx.o: In function `CRect::CRect(int, int, int, int)':
rect.cpp:(.text+0x34): undefined reference to `vtable for CRect'
/tmp/cckeSZdQ.o: In function `CCircle::CCircle(int, int, double)':
circle.cpp:(.text+0x32): undefined reference to `vtable for CCircle'
collect2: ld returned 1 exit status

Q.
1) rect 와 circle 모두 shape를 상속받은 클래스인데, 왜 중복정의를 했다고 오류를 내는것인가요?
2) 이 경우에서의 vtable 오류는 도대체 어떻게 처리해야 하는건가요?

질문하기에 코드가 조금 길어서 불편을 드리게 됬지만
어떻게해서든 오류의 이유를 알고 싶습니다
아무쪼록 도움 부탁드리겠습니다!

익명 사용자의 이미지

1) 에러 메세지를 잘 읽으셔야지요~. 중복 정의는 Print 함수이지 CRect 나 CCircle이 아닙니다. Print를 정의할 때에 class name qualifier를 깜박하셨어요.
2) Print를 제대로 정의하면 아마 2)도 해결될듯 합니다. (참고 https://gcc.gnu.org/faq.html#vtables)

kimhyuns55의 이미지

정말 바보같은 실수를 해놓고 질문글을 올려버렸네요..
정말 부끄러워집니다 :'(

문제는 덕분에 해결되었습니다
답변 감사드립니다 ㅠㅠ

pynoos의 이미지

참고로 -v 옵션을 넣고 실행해보시고, c/c++ 의 오류메시지는 크게 전처리기(cpp), 컴파일러(cc, c++), 링커(ld)로 구별됩니다. 위의 문제는 링커의 문제입니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.