2013-01-15 62 views
0

我的工作++編譯第15章我或多或少複製的代碼直出書爲Acellerated c中的代碼,除了在他們定義的東西就像有些地方是頭文件中的類體中的構造函數,並將它們分開以避免鏈接錯誤。編譯器會將實際定義

下面是代碼;我試圖在Visual Studio 2010中編譯它,但不幸的是它失敗了。它告訴我它不能創建「String_Pic」和其他派生類(Frame_Pic,HCat_Pic和VCat_Pic)的實例,因爲它表示它們仍然是抽象類。它說罪魁禍首是「顯示」功能,它表示它是未定義的。但是,我明確地爲每個派生類定義它,如下所示。

這是怎麼回事?

頁眉:

#ifndef _GUARD_PIC_BASE_H 
#define _GUARD_PIC_BASE_H 

    #include "Ptr.h" 
    #include <iostream> 
    #include <string> 
    #include <vector> 


    class Picture; 

    class Pic_base { 
     friend std::ostream& operator<<(std::ostream&, const Picture&); 
     friend class Frame_Pic; 
     friend class HCat_Pic; 
     friend class VCat_Pic; 
     friend class String_Pic; 


     typedef std::vector<std::string>::size_type ht_sz; 
     typedef std::string::size_type wd_sz; 


     virtual wd_sz width() const = 0; 
     virtual ht_sz height() const = 0; 
     virtual void display(std::ostream, ht_sz, bool) const = 0; 

    public: 
     virtual ~Pic_base(){ } 

    protected: 
     static void pad(std::ostream&, wd_sz, wd_sz); 
    }; 

    // public interface class and operations 
    class Picture { 
     friend std::ostream& operator<<(std::ostream&, const Picture&); 
     friend Picture frame(const Picture&); 
     friend Picture hcat(const Picture&, const Picture&); 
     friend Picture vcat(const Picture&, const Picture&); 

    public: 
     Picture(const std::vector<std::string>& = 
      std::vector<std::string>()); 
    private: 
     Picture(Pic_base* ptr); //here's one difference 
     Ptr<Pic_base> p; 
    }; 


    Picture frame(const Picture&); 
    Picture hcat(const Picture&, const Picture&); 
    Picture vcat(const Picture&, const Picture&); 
    std::ostream& operator<<(std::ostream&, const Picture&); 

    class String_Pic: public Pic_base { 
     friend class Picture; 
     std::vector<std::string> data; 
     String_Pic(const std::vector<std::string>&); 

     wd_sz width() const; 
     ht_sz height() const; 
     void display(std::ostream&, ht_sz, bool) const; 
    }; 

    class VCat_Pic: public Pic_base { 
     friend Picture vcat(const Picture&, const Picture&); 
     Ptr<Pic_base> top, bottom; 
     VCat_Pic(const Ptr<Pic_base>&, const Ptr<Pic_base>&); 

     wd_sz width() const; 
     ht_sz height() const; 
     void display(std::ostream&, ht_sz, bool) const; 
    }; 

    class HCat_Pic: public Pic_base { 
     friend Picture hcat(const Picture&, const Picture&); 
     Ptr<Pic_base> left, right; 
     HCat_Pic(const Ptr<Pic_base>&, const Ptr<Pic_base>&); 

     wd_sz width() const; 
     ht_sz height() const; 
     void display(std::ostream&, ht_sz, bool) const; 
    }; 

    class Frame_Pic: public Pic_base { 
     friend Picture frame(const Picture&); 
     Ptr<Pic_base> p; 
     Frame_Pic(const Ptr<Pic_base>& pic); 

     wd_sz width() const; 
     ht_sz height() const; 
     void display(std::ostream&, ht_sz, bool) const; 
    }; 

#endif 

的.cpp /執行文件:

#include "Ptr.h" 
#include "Pic_Base.h" 
#include <vector> 
#include <string> 
#include <algorithm> 
#include <iostream> 

using namespace std; 

//Picture-Specific Functions: 

Picture::Picture(Pic_base* ptr):p(ptr) {} 

Picture::Picture(const vector<string>& v): p(new String_Pic(v)) { } 

//Frame-Specific Functions: 

Frame_Pic::Frame_Pic(const Ptr<Pic_base>& pic): p(pic) {} 

Pic_base::wd_sz Frame_Pic::width() const { return p->width() + 4; } 

Pic_base::ht_sz Frame_Pic::height() const { return p->height() + 4; } 

void Frame_Pic::display(ostream& os, ht_sz row, bool do_pad) const{ 
    if (row >= height()) { 
     // out of range 
     if (do_pad) 
      pad(os, 0, width()); 
    } else { 
     if (row == 0 || row == height() - 1) { 

      // top or bottom row 
      os << string(width(), '*'); 
     } else if (row == 1 || row == height() - 2) { 

      // second from fop or bottom row 
      os << "*"; 
      pad(os, 1, width() - 1); 
      os << "*"; 
     } else { 
      // interior row 
      os << "* "; 
      p->display(os, row - 2, true); 
      os << " *"; 
     } 
    } 
} 

Picture frame(const Picture& pic){ 
    return new Frame_Pic(pic.p); 
} 

//HCat-Specific Functions: 

HCat_Pic::HCat_Pic(const Ptr<Pic_base>& l, const Ptr<Pic_base>& r): left(l), right(r) { } 

HCat_Pic::HCat_Pic(const Ptr<Pic_base>& l, const Ptr<Pic_base>&r): 
left(l), right(r) { } 

Pic_base::wd_sz width() const { return left->width() + right->width(); } 

Pic_base::ht_sz height() const { return max(left->height(), right->heigth()); } 

void HCat_Pic::display(ostream& os, ht_sz row, bool do_pad) const{ 
    left->display(os, row, do_pad || row < right->height()); 
    right->display(os, row, do_pad); 
} 

Picture hcat(const Picture& l, const Picture& r){ 
    return new HCat_Pic(l.p, r.p); 
} 

//VCat-Specific Functions: 

VCat_Pic::VCat_Pic(const Ptr<Pic_base>& t, const Ptr<Pic_base>& b): top(t), bottom(b) { } 

Picture vcat(const Picture& t, const Picture& b){ 
    return new VCat_Pic(t.p, b.p); 
} 

Pic_base::wd_sz VCat_Pic::width() const { 
    return max(top->width(), bottom->width()); 
} 

Pic_base::ht_sz VCat_Pic::height() const{ 
    return top->height() + bottom->height(); 
} 

void VCat_Pic::display(ostream& os, ht_sz row, bool do_pad) const{ 
    wd_sz w = 0; 
    if (row < top->height()) { 
     // we are in the top subpicture 
     top->display(os, row, do_pad); 
     w = top->width(); 
    } else if (row < height()) { 
     // we are in the bottom subpicture 
     bottom->display(os, row - top->height(), do_pad); 
     w = bottom->width(); 
    } 
    if (do_pad) 
     pad(os, w, width()); 
} 

//String_Pic-Specific Functions: 

String_Pic::String_Pic(const std::vector<std::string>& v): data(v) { } 

Pic_base::ht_sz String_Pic::height() const { return data.size(); } 

Pic_base::wd_sz String_Pic::width() const{ 
    Pic_base::wd_sz n = 0; 
    for (Pic_base::ht_sz i = 0; i != data.size(); ++i) 
     n = max(n, data[i].size()); 
    return n; 
} 

void String_Pic::display(ostream& os, ht_sz row, bool do_pad) const{ 
    wd_sz start = 0; 

    // write the row if we're still in range 
    if (row < height()) { 
     os << data[row]; 
     start = data[row].size(); 
    } 

    // pad the output if necessary 
    if (do_pad) 
     pad(os, start, width()); 
} 

//Pic_base-Specific functions: 
void Pic_base::pad(std::ostream& os, wd_sz beg, wd_sz end) { 
    while (beg != end) { 
     os << " "; 
     ++beg; 
    } 
} 


//Non-Specific Functions: 

ostream& operator<<(ostream& os, const Picture& picture){ 
    const Pic_base::ht_sz ht = picture.p->height(); 
    for (Pic_base::ht_sz i = 0; i != ht; ++i) { 
     picture.p->display(os, i, false); 
     os << endl; 
    } 
    return os; 
} 
+2

仔細看看你的基類原型。 – chris

回答

6

您聲明純虛函數,通過數值採取ofstream對象,而所有的子類定義它爲參考一個

virtual void display(std::ostream, ht_sz, bool) const = 0; 

VS

void display(std::ostream&, ht_sz, bool) const; 
         ^
+0

啊,它總是小事!拼寫錯誤確實是我的舊剋星。謝謝一堆。 –

+0

@AndyIsbell歡迎您!它發生。你是幸運的基本功能是純虛的,否則它不會必須甚至是一個錯誤,爲什麼他們在新版本中 –

4

Pi_base聲明display與此簽名:

virtual void display(std::ostream, ht_sz, bool) const = 0; 

但是你的派生類與此簽名聲明它:

void display(std::ostream&, ht_sz, bool) const; 

有限公司仔細比較它們,你會發現你的基類需要std::ostream,而你的派生類需要std::ostream&

+0

謝謝複製Java的'override'關鍵字我猜這,我無法相信我錯過了。我很專注於發現邏輯錯誤。 –