2011-12-24 40 views
8

Tôi đang làm việc trên một trong những thách thức lập trình trong cuốn sách Bắt đầu với C++ Early Objects 7th Edition và một trong các bài tập yêu cầu tạo một lớp có nguồn gốc từ lớp chuỗi STL. Tôi đang đăng câu hỏi với mục đích hiểu những gì tôi được phép làm và cách tôi phải triển khai giải pháp để không ai đưa ra đề xuất nâng cao hơn.Làm cách nào để truy cập các biến thành viên trong lớp chuỗi STL?

- Câu hỏi y như đã chép trong văn bản -

Palindrome Testing

Một Palindrome là một chuỗi mà đọc cùng lạc hậu như về phía trước. Ví dụ: các từ mẹ, cha, madamradar là palindromes. Viết class Pstring có nguồn gốc từ STL string class. Pstring class thêm chức năng thành viên

bool isPalindrome() 

xác định xem chuỗi có phải là palindrome hay không. Bao gồm một hàm tạo lấy một đối tượng STL string làm tham số và chuyển nó tới hàm tạo lớp cơ sở chuỗi. Kiểm tra lớp của bạn bằng cách có một chương trình chính yêu cầu người dùng nhập chuỗi. Chương trình sử dụng chuỗi để khởi tạo một đối tượng Pstring và sau đó gọi isPalindrome() để xác định chuỗi được nhập là palindrome hay không.

Bạn có thể thấy hữu ích khi sử dụng toán tử subscript [] của lớp chuỗi: nếu str là đối tượng chuỗi và k là số nguyên, sau đó str [k] trả về ký tự ở vị trí k trong chuỗi.

- End -

câu hỏi chính của tôi là làm thế nào để truy cập vào các biến thành viên nắm giữ đối tượng chuỗi của tôi nếu lớp tôi bắt nguồn từ Pstring là một lớp học tôi đã không viết và tôi không biết làm thế nào nó thực hiện các thành viên của nó?

Ví dụ,

#include <string> 
using namespace std; 

class Pstring : public string 
{ 
public: 
    Pstring(std::string text) 
    : string(text) { } 

    bool isPalindrome() 
    { 
    // How do I access the string if I am passing it to the base class? 

    // What I think I should do is... 
    bool is_palindrome = true; 
    auto iBegin = begin(); 
    auto iEnd = end() - 1; 

    while (iBegin < iEnd && is_palindrome) 
    { 
     if (*iBegin++ != *iEnd--) 
     is_palindrome = false; 
    } 

    return is_palindrome; 

    // But I think this is wrong because... 
    // #1 The book did not discuss the keyword auto yet 
    // #2 The book discussed when a class is derived from another class, 
    // how the members from super class will be accessible to the sub class. 
    // However, with this assignment, I don't see how to access the members. 
    } 
} 

Lý do tôi cảm thấy như tôi đang làm này không chính xác là do sự phân công đề cập đến sử dụng ký hiệu phụ, tuy nhiên, tôi không hiểu làm thế nào để sử dụng các ký hiệu subscript nếu tôi don' t biết tên của biến nơi chuỗi được lưu trữ.

Bất kỳ trợ giúp nào cũng sẽ được đánh giá cao bởi vì tác giả không cung cấp giải pháp trừ khi tôi là người hướng dẫn khá lame theo ý kiến ​​của tôi. Nó có thể đã làm với thực tế rằng đây là một văn bản học thuật.

+6

Không bao giờ lấy được từ các lớp học STL. Luôn luôn là một ý tưởng tồi. Tại sao bạn không thử sáng tác thay thế? – Lalaland

+5

Tác giả có thể không cung cấp giải pháp vì anh ta là kẻ ngốc. – Duck

+0

@Ethan Steinberg Tôi hoàn toàn đồng ý, tuy nhiên, nhiệm vụ này đặc biệt yêu cầu làm điều đó. –

Trả lời

3

Bạn không nên kế thừa từ std :: string, vì nó không được thiết kế cho điều đó, cũng như bạn không cần phải tìm palindrome.

Xem này: Inheriting and overriding functions of a std::string?

giải pháp Palindrome (từ câu hỏi này: Check if a string is palindrome Được liên kết từ này: C++ Palindrome finder optimization)

#include <algorithm> 

bool isPal(const string& testing) { 
    return std::equal(testing.begin(), testing.begin() + testing.size()/2, testing.rbegin()); 
} 

chất lượng của cuốn sách đó có vẻ đáng ngờ. Các chức năng miễn phí (tùy thuộc vào người bạn yêu cầu) hầu như luôn được ưu tiên hơn các chức năng của thành viên và đặc biệt được ưu tiên hơn thừa kế.


Nếu bạn phải sử dụng thừa kế:

class Pstring : public string 
{ 
    //... 

    bool isPalindrome() 
    { 
     return std::equal(begin(), begin() + size()/2, rbegin()); 

     // as a side-note, 'iterator' will refer to the inherited return type of begin() 
     // Also, 'operator[](x)' will call the subscript operator 
    } 
}; 
+0

Cảm ơn bạn đã phản hồi. Tôi biết rằng đây không phải là thực hành tốt. Tuy nhiên, nhiệm vụ cụ thể yêu cầu tôi thực hiện giải pháp của tôi theo cách tôi đang cố gắng ở trên. Bằng cách tạo một lớp có nguồn gốc từ lớp chuỗi STL và sau đó tạo một hàm để kiểm tra nếu một chuỗi là một palindrome. Tôi đang cố hoàn thành nhiệm vụ. Tôi không thể sử dụng bất kỳ phương pháp nâng cao hơn hoặc thực hiện giải pháp của riêng tôi mà deviates từ cách phân công yêu cầu nó. –

+0

@ fhaddad78 Bạn chỉ có thể quấn mã đó vào một hàm thành viên. std :: chức năng thành viên của chuỗi vẫn có sẵn. – Pubby

+0

Cảm ơn bạn đã phản hồi. Tôi bỏ qua gọi điện thoại nhà điều hành [] (x) trực tiếp và đã cố gắng tìm ra cách sử dụng ký hiệu infix. –

0

Nếu bạn không muốn sử dụng ô tô, sau đó bạn có thể chỉ cần sử dụng std::string::iterator thay vào đó, đó là những gì auto được giải quyết để anyways trong trường hợp này.

Vì vậy, vấn đề # 1 được thỏa mãn.


Khi bạn đang gọi begin()end() bạn đang gọi các thành viên begin()end() trong std :: string lớp cha.

Do đó, vấn đề # 2 được thỏa mãn.

1

Sách không bao gồm auto vì từ khóa đó chỉ mới được thêm vào ngôn ngữ. Nếu trình biên dịch của bạn đã hơn một tuổi hoặc không phải là một trong những tên tuổi lớn thì có lẽ nó không hỗ trợ nó.

Đối với vấn đề này, bạn không cần truy cập bất kỳ biến thành viên nào để có giải pháp thích hợp, do đó không cần phải lo lắng về chúng là gì hoặc liệu chúng có thể truy cập được hay không. Điều tốt, bởi vì không cái nào được chỉ định bởi tiêu chuẩn - đó là tất cả các chi tiết thực hiện được định nghĩa bởi trình biên dịch cụ thể của bạn, và nếu bạn thấy mình đào sâu bạn nên tự hỏi bản thân mình đang làm gì sai.

Tất nhiên các chức năng thành viên của lớp cha được truy cập chính xác như các hàm thành viên của lớp con - bạn chỉ cần gọi chúng.

Tình trạng quá tải của nhà điều hành thành viên phức tạp hơn một chút, nhưng vẫn không quá tệ. Bạn cần cung cấp cá thể để gọi chúng chống lại, là *this. Bạn cũng có thể gọi cho họ bằng từ khóa operator nhưng theo ý kiến ​​của tôi thì có một chút vụng về.

if ((*this)[i] == (*this)[j]) 

if (operator[](i) == operator[](j)) 
+1

'tự động 'từ khóa đã được xung quanh kể từ khi B.' auto' làm một cái gì đó hữu ích là những gì gần đây đã được thêm vào. – Pubby

+0

@Mark Ransom OK. Tôi sẽ đánh phấn này chỉ là một nhiệm vụ xấu tất cả cùng nhau. Tôi đã thực sự bối rối bởi vấn đề này bởi vì nó đề cập đến việc sử dụng ký hiệu subscript trong giải pháp của tôi mà tôi không hiểu làm thế nào để làm trừ khi tôi quá tải toán tử subscript hoặc trừ khi chuỗi của tôi đang ngồi trong biến thành viên mà tôi có thể định vị, nhưng có vẻ như tôi không thể. –

+1

@ fhaddad78, tôi đã cập nhật câu trả lời để bao gồm các toán tử thành viên. –

0

Hãy thử điều này:

#include <string> 

class Pstring : public std::string 
{ 
public: 
    Pstring(const std::string &text) 
     : std::string(text) { } 

    bool isPalindrome() 
    { 
     std::string::size_type len = length(); 
     std::string::size_type half = len/2; 
     for (std::string::size_type idx = 0; idx < half; ++idx) 
     { 
      if ((*this)[idx] != (*this)[len-idx-1]) 
       return false; 
     } 
     return true; 
    } 
}; 
Các vấn đề liên quan