2017-06-22 17 views
5

Tôi gặp sự cố với chức năng final. Tôi muốn "dừng" sự đa hình trong một lớp nhưng tôi vẫn muốn tạo ra cùng một hàm trong một lớp dẫn xuất.Có thể có một lớp dẫn xuất thừa hưởng hàm cuối cùng nhưng tạo ra cùng một hàm (không ghi đè) không?

Something như thế này:

class Base{ 
    protected: 
     int _x, _y; 
    public: 
     Base(int x = 0, int y = 0) : _x(x), _y(y){}; 
     int x() const { return _x; } 
     int y() const { return _y; } 
     virtual void print()const{ cout << _x*_y << endl; } 
}; 

class Derived : public Base{ 
    public: 
     Derived(int x = 0, int y = 0) : Base(x, y){} 
     void print()const final { cout << _x*_y/2.0 << endl; } // final inheritance 
}; 

class NonFinal : public Derived{ 
     void print()const{ cout << "apparently im not the last..." << endl } 
    // here i want a new function. not overriding the final function from Derived class 
}; 
+2

Theo nguyên tắc chung, tôi sẽ gọi lỗi thiết kế trên mã ẩn các thành viên được kế thừa (ngoại trừ rõ ràng là ghi đè hàm ảo được thừa kế). Tôi sẽ đề nghị gọi phương thức khác trong 'NonFinal'. Nếu bạn thấy mình cần phải làm điều này, một cái gì đó về thiết kế OO của bạn là xấu. – cdhowie

Trả lời

2

Xin lỗi, nhưng nó không thể tạo ra một hàm trong một lớp được thừa kế khi một hàm có cùng tên tồn tại như final trong lớp cơ sở. Bạn sẽ cần suy nghĩ lại về thiết kế của mình.

Vấn đề xuất phát từ thực tế là khai báo hàm trong lớp dẫn xuất có cùng tên với hàm trong lớp cơ sở được coi là cố gắng ghi đè liệu từ khóa override có hiện diện hay không (vì lý do lịch sử, tôi giả định). Vì vậy, bạn không thể "tắt" ghi đè.

Dưới đây là một tiêu chuẩn trích dẫn liên quan:

§ 10,3/4 [class.virtual]

Nếu một hàm ảo f trong một số lớp B được đánh dấu bằng các virt-specifierfinal và trong một lớp D có nguồn gốc từ B một hàm D::f ghi đè B::f, chương trình không đúng định dạng. [Ví dụ:

struct B { 
    virtual void f() const final; 
}; 
struct D : B { 
    void f() const; // error: D::f attempts to override final B::f 
}; 

-end

2

Tôi nghĩ rằng đây là một câu hỏi thực nghiệm, vì thực sự bạn nên suy nghĩ lại những gì bạn đang làm khi bạn yêu cầu để "ghi đè lên một chức năng cuối cùng" (âm thanh mâu thuẫn, phải không?).

Nhưng bạn có thể giới thiệu tham số "giả", tức là void NonFinal::print(int test=0)const, điều này cho phép trình biên dịch xử lý chức năng thành viên như một hàm khác. Không chắc chắn nếu điều đó giải quyết "vấn đề" của bạn; nhưng ít nhất nó giới thiệu một hàm có cùng tên, mà vẫn có thể được gọi mà không truyền một đối số, và được tách biệt với các đối số của DerivedBase.

class NonFinal : public Derived{ 
public: 
    void print(int test=0)const{ cout << "apparently im not the last..." << endl; } 
}; 

int main() { 

    Base b (10,10); 
    Derived d (20,20); 
    NonFinal nf; 
    Base *bPtr = &d; 
    bPtr->print(); // gives 200 
    bPtr = &nf; // gives 0 
    bPtr->print(); 
    nf.print(); // gives "apparantly..." 
} 
Các vấn đề liên quan