2012-02-15 61 views
19

Tôi muốn tạo một đối số cho một trong các hàm thành viên tùy chọn. Khi không có đối số nào được cung cấp, nó sẽ sử dụng một biến thành viên.Làm thế nào để sử dụng biến thành viên làm đối số mặc định trong C++?

Tuy nhiên, khi tôi đã cố gắng để biên dịch nó nó cho thấy "lỗi: sử dụng không hợp lệ của không tĩnh thành viên dữ liệu 'Object :: initPos'"

Chỉ cần để cô lập các vấn đề, tôi đã cố gắng mặc định một kiểu int và nó được biên soạn tốt. Tôi tự hỏi vấn đề với mã của tôi là gì và cách tôi có thể sử dụng hàm thành viên làm giá trị mặc định.

Cảm ơn sự giúp đỡ của bạn!

Object.h

class Object 
{ 
    public: 
     ... 
     void MoveTo(double speed, Point position); 

    protected: 
     Point initPos; 
     Point currPos; 

}; 

Object.c

void Object::MoveTo(double speed, Point position = initPos) 
{ 
    currPos = postion; 
} 

Point.h

class Point 
{ 
    ... 

    private: 
     double x; 
     double y; 
     double z; 
}; 
+1

Câu hỏi của bạn làm tôi đẻ trứng này một: http://stackoverflow.com/questions/9286801/valid-expressions-for-default-function-arguments –

Trả lời

30

Biểu thức đối số mặc định cho hàm thành viên chỉ có thể phụ thuộc vào những thứ nằm trong lớp hoặc phạm vi toàn cục. Đối số mặc định cũng phải được chỉ định trong khai báo của phương thức (ví dụ: trong tệp tiêu đề).

Để giải quyết vấn đề này, bạn cần 2 quá tải của phương thức MoveTo. Một trong đó có 1 đối số và một đối số khác có 2 đối số. Phương thức lấy 1 đối số gọi phương thức khác, chuyển theo giá trị mà bạn coi là mặc định.

void Object::MoveTo(double speed) 
{ 
    MoveTo(speed, initPos); 
} 

void Object::MoveTo(double speed, Point position) 
{ 
    // Everything is done here. 
} 

Lưu ý rằng khi bạn thực hiện cuộc gọi MoveTo(double)MoveTo(double, Point), nó cho phép bạn viết thực hiện MoveTo chỉ một lần, qua đó tôn trọng các nguyên tắc DRY.

+0

Cảm ơn! Tôi biết rằng tôi có thể làm theo cách này. Tôi đã tự hỏi nếu có một cách ngắn hơn để làm điều đó, chẳng hạn như làm cho nó một đối số mặc định. Nhưng tôi đoán đây sẽ là cách duy nhất để làm điều đó. – tuzzer

+0

Sau đó, nếu, thay vì chỉ là một đối số tùy chọn, tôi có nhiều đối số trong số đó? nói void Object :: MoveTo (tốc độ gấp đôi, vị trí điểm = initPos, điểm a = m_a, điểm b = m_b, điểm c = m_c) sau đó tôi sẽ không phải thực hiện nhiều chức năng ??? – tuzzer

+0

@MatthewChan: Thật không may, vâng. Thay vì chuyển nhiều đối số, có lẽ bạn có thể thay đổi thiết kế để người dùng chuyển một đối tượng.Đối tượng này đã chứa các giá trị mặc định hợp lý và người dùng chỉ thay đổi các đối tượng cần phải khác. Nếu bạn quyết định làm theo cách này, bạn có thể quan tâm đến thành tố Chaining phương thức để thiết lập nhiều thông số ngắn gọn hơn (http://en.wikipedia.org/wiki/Method_chaining). –

10

Mặc định giá trị không phải là một phần của nguyên mẫu, tức là họ đang giải quyết bởi người gọi, không phải bởi chính hàm đó. Vì vậy, trước tiên, họ phải được hiển thị cho người gọi. Thứ hai, họ không thể truy cập các thành viên được bảo vệ của lớp. (Tôi khá chắc chắn bạn thậm chí không thể sử dụng các thành viên công cộng làm mặc định, nhưng tôi quá mệt mỏi để kiểm tra.)

Để giải quyết vấn đề, hãy sử dụng quá tải chuỗi như được đề xuất trong các câu trả lời khác.

+0

Cảm ơn. Tôi đã thử thay đổi initPos thành công khai, nhưng như bạn đã nói, nó vẫn không hoạt động. Vì vậy, nó là chúng ta chỉ có thể sử dụng liên tục như đối số mặc định (như không phải chức năng thành viên, một cái gì đó mà bạn có thể gõ ra) ?? – tuzzer

1

Bạn có thể quá tải hàm thành viên của bạn như thế:

void Object::MoveTo(double speed, Point position) { 
    .... 
} 

void Object::MoveTo(double speed) { 
    Point position = this->initPos; 

    MoveTo(speed, position); 
} 
+0

tiếc là công việc duy nhất xung quanh đó có thể nhận được công việc làm, trông xấu xí mặc dù :( – Argento

Các vấn đề liên quan