Board logo

標題: [操作疑難] C++ Virtual 問題 [打印本頁]

作者: ghostkcleung    時間: 2021-3-28 14:20     標題: C++ Virtual 問題

Rectangle 有無可能唔 Override draw 嘅情況下,
可以 Call 得到 Screen::drawShape(Rectangle*) ?

class Shape {
    public:
        virtual void draw ( Screen* scr ) {
              scr -> drawShape ( this );
       }
}

class Rectangle:public Shape { }

class Screen {
    public:
       void drawShape ( Shape *s ) {
            cout << "Draw Shape" ;
       }

       void drawShape ( Rectangle *r ) {
            cout  << "Draw Rectangle" ;
       }
}
作者: KinChungE    時間: 2021-3-28 14:32

做左type casting先?
作者: ghostkcleung    時間: 2021-3-28 16:01

既然佢係 virtual,
expect 唔只 1 個 inherit 啦。

做左type casting先?
KinChungE 發表於 2021-3-28 14:32

作者: BudaHK    時間: 2021-3-28 23:24

Let's put aside C++ first. The design is really hard to understand. Is it really needed to do it that way?
作者: ghostkcleung    時間: 2021-3-28 23:34

我自己認為呢個 design 係一個幾 common 嘅諗法

Shape:
   Rectangle
   Triangle
   Circle ...

Driver:
   GenericDriver
      CustomDriverA
      CustomDriverB

將來如果有人想整個 CustomDriverC
嘅話,佢可以唔洗改 Parents 嘅情況下,
自己 Overload 一個 implement。
作者: ghostkcleung    時間: 2021-3-28 23:37

我寫緊嘅 Library 其實就係爭呢樣嘢

https://github.com/ghostkcleung/tft_framework
作者: KinChungE    時間: 2021-3-29 10:36

我反如唔係好明, 如果個drawShape係專俾Rectangle用, 點解唔放去Rectangle class override draw(), 而要放響Screen度overload?
作者: ghostkcleung    時間: 2021-3-29 16:46

我反如唔係好明, 如果個drawShape係專俾Rectangle用, 點解唔放去Rectangle class override draw(), 而要放 ...
KinChungE 發表於 2021-3-29 10:36


因為其實唔只 Rectangle 一個 Shape
作者: KinChungE    時間: 2021-3-29 16:59

因為其實唔只 Rectangle 一個 Shape
ghostkcleung 發表於 2021-3-29 16:46


咁咪每個shape既child class各自override
OO原意就係咁
響parent做哂child要做既野有D本末倒置
作者: ghostkcleung    時間: 2021-3-30 00:56

咁咪每個shape既child class各自override
OO原意就係咁
響parent做哂child要做既野有D本末倒置 ...
KinChungE 發表於 2021-3-29 16:59


依家唯有係咁。

變咗每個 Child override 都係寫重複嘅嘢。
作者: it_jobs    時間: 2021-3-30 10:00

依家唯有係咁。

變咗每個 Child override 都係寫重複嘅嘢。
ghostkcleung 發表於 2021-3-30 00:56


有幾大重覆性先?

可否
draw() {
predraw();
drawSharp();
postdraw();
}

predraw(), postdraw() 放係 parent 到?
作者: ghostkcleung    時間: 2021-3-30 20:27

但都係分唔到 Type 。

有幾大重覆性先?

可否
draw() {
predraw();
drawSharp();
postdraw();
}

predraw(), postdraw()  ...
it_jobs 發表於 2021-3-30 10:00

作者: ghostkcleung    時間: 2021-3-30 20:39

本帖最後由 ghostkcleung 於 2021-3-31 19:41 編輯

原本個佈局大約係咁樣…

class Shape {
  void draw(Screen *scr) { scr->drawShape (this); }
  virtual void draw Generic(Screen *scr)=0;
};

class Rectangle : public Shape {
  void drawGeneric(Screen scr) {
     cout << "Rectangle" << end;
  }
}

class Circle : public Shape {
  void drawGeneric(Screen scr) {
     cout << "Circle" << end;
  }
}

class Screen {
  void drawShape(Shape *s) {
    s->drawGeneric(this);
  }
}

Class SubScreen {
  void drawShape(Rectangle *r){
     cout << "won't be called";
  }
}
作者: ghostkcleung    時間: 2021-3-30 20:41

本帖最後由 ghostkcleung 於 2021-3-30 22:02 編輯

我諗法係,將來如果有新嘅 Shape,
我唔須要搞個 Screen。
又如果我有新嘅 Screen,
對 Shape 有自己獨特嘅 draw 法,
可以直接 Override,
亦唔須要去搞啲 Shape。

但依家無辦法做呢樣嘢。
作者: cosmonova    時間: 2021-3-30 23:45

OO 而言,到明日有新Shape... say "Star".. 今日點會知Star::Draw點implement? 唔係叫迫住要copy, 係想model "Star"成為一個Shape,就要be a Shape
作者: it_jobs    時間: 2021-3-31 12:34

本帖最後由 it_jobs 於 2021-3-31 16:13 編輯
但都係分唔到 Type 。
ghostkcleung 發表於 2021-3-30 20:27


我懶啫

//----------------------------------
//  test.cpp
//----------------------------------
#include "Rect.h"
#include <iostream>

using namespace std;

int main()
{
    cout << "CPP Test...." << endl;
    Rect *rect = new Rect();
    rect->Draw();
    return 0;
}

//----------------------------------
// Sharp.h
//----------------------------------
class Sharp
{
public:
    virtual void Draw();
    char name[200] = "Sharp";

public:
    virtual void PreDraw();
    virtual void ObjDraw();
    virtual void PostDraw();
};

//----------------------------------
// Sharp.cpp
//----------------------------------
#include <iostream>
#include "Sharp.h"

using namespace std;

void Sharp::PreDraw()
{
    cout << "In Parent PreDraw" << endl;
}

void Sharp::ObjDraw()
{
    cout << "In Parent ObjDraw" << endl;
}

void Sharp::PostDraw()
{
    cout << "In Parent PostDraw" << endl;
}

void Sharp::Draw()
{
    cout << "In Parent Draw" << endl;
    this->PreDraw();
    this->ObjDraw();
    this->PostDraw();
}

//----------------------------------
// Rect.h
//----------------------------------
#include "Sharp.h"

class Rect : public Sharp
{
public:
    virtual void ObjDraw();
};

//----------------------------------
// Rect.cpp
//----------------------------------
#include <iostream>
#include "Rect.h"

using namespace std;
void Rect::ObjDraw()
{
    cout << "In Rect::ObjDraw" << endl;
}

//----------------------------------
// Console output
//----------------------------------
CPP Test....
In Parent Draw
In Parent PreDraw
In Rect::ObjDraw
In Parent PostDraw
作者: it_jobs    時間: 2021-3-31 16:27

[quote]原本個佈局大約係咁樣…

class Shape {
  void draw(Screen *scr) { scr->drawShape (this); }
  virtual  ...
[size=2][color=#999999]ghostkcleung 發表於 2021-3-30 20:39[/color] [url=https://www.hkepc.com/forum/redirect.php?goto=findpost&pid=40253574&ptid=2613236][img]//i.hkepc.net/forum/common/back.gif[/img][/url][/size][/quote]

試想一下, 如果 drawShape 點用.

A)
Screen s;
Circle c;
c.drawShape()?

Shape[] shapeList = {...};
for(int i =0; i < sizeof(shapeList)/sizeof(shapeList[0]); i++) {
   shapeList\[i\].drawShape();
}

B)
Screen s;
Circle c;
c.drawShape(&c); // or
s.drawShape(&c);

Shape[] shapeList = {...};
for(int i =0; i < sizeof(shapeList)/sizeof(shapeList[0]); i++) {
   s.drawShape(shapeList[i]);
}

正常別一位師兄話齋.
如果 Shape 要包山包海, 咁當有粒沙新生出黎, 你就要改 shape 嘅 code, 去對應新 shape 嘅 drawing.
個新shape 由邊個 define, 入面個 logic 係點做, 邊個知呢?
假設唔係1 man band, 有人負責 shape base class, 有人負責起新 shape. 咁就要起新 shape 嘅人向 shape base class owner 要求改變.  好似怪怪地.
又有個問題係, 當同時起幾個新 shape, 大家都要衝去改 base class, 又好似制造不必要嘅 merge problem.
作者: ghostkcleung    時間: 2021-3-31 19:38

我個諗法係每個 Shape define 出嚟嗰陣,
有自己嘅 Generic 方法處理 Draw。

當 Screen 無自己方法處理呢個 Shape 嗰陣,
就會用 Shape 嘅 Generic;

如果將來有新嘅 Screen,
對 Shape 有自己獨特處理方法,
亦有自己嘅 Override Draw。
作者: KinChungE    時間: 2021-3-31 20:18

我個諗法係每個 Shape define 出嚟嗰陣,
有自己嘅 Generic 方法處理 Draw。

當 Screen 無自己方法處理呢 ...
ghostkcleung 發表於 2021-3-31 19:38


即係講緊M款Screen + N款Shape = M x N

我個人會咁做:
Shape <-- GenericShape <-- Triangle/Rectangle

有咩Generic既放去中間果層class handle, 獨立唔同既就放去最child
日後加Screen的話, 可以先去GenericShape果度加翻D fallback code先
作者: it_jobs    時間: 2021-4-1 09:43

本帖最後由 it_jobs 於 2021-4-1 09:51 編輯
我個諗法係每個 Shape define 出嚟嗰陣,
有自己嘅 Generic 方法處理 Draw。

當 Screen 無自己方法處理呢 ...
ghostkcleung 發表於 2021-3-31 19:38


如果我個寫法.  你新 class 只要唔寫多個 ObjDraw() method, 就自然 call base ObjDraw().
利申, 個方法應該係唔知邊到睇返黎, 應該唔係我發明, 寫住"我個寫法"只係講我帶出黎.

//--------------------------------------------------
// Circle.h
//--------------------------------------------------
#include "Shape.h"

class Circle : public Shape
{
};

//--------------------------------------------------
// test.cpp
//--------------------------------------------------
#include <iostream>
#include "DevToolBox.h"

#include "Rect.h"
#include "Circle.h"

using namespace std;

int main()
{
    cout << "In " << __METHOD_NAME__ << endl;
    Rect *rect = new Rect();
    rect->Draw();

    Circle circle;
    cout << "Drawing Circle begin" << endl;
    circle.Draw();
    cout << "Drawing Circle end" << endl;

    return 0;
}


//--------------------------------------------------
//  Console output
//--------------------------------------------------
$ ./test
In main()
In Shape::Draw()
In Shape::PreDraw()
In Rect::ObjDraw()
In Shape::PostDraw()
Drawing Circle begin
In Shape::Draw()
In Shape::PreDraw()
In Shape::ObjDraw()
In Shape::PostDraw()
Drawing Circle end





歡迎光臨 電腦領域 HKEPC Hardware (https://www.hkepc.com/forum/) Powered by Discuz! 7.2