Thắc mắc về con trỏ, cấp phát động

Xin chào mọi người.
Em được biết là con trỏ của kiểu dữ liệu nào hoặc đối tượng nào thì mới trỏ được đến kiểu dữ liệu hoặc đối tượng đấy.
Em có đoạn code được lấy trên https://cplusplus.com/doc/tutorial/polymorphism/
Và có nội dung như sau:

// pointers to base class
#include <iostream>
using namespace std;

class Polygon {
protected:
    int width, height;
public:
    void set_values(int a, int b)
    {
        width = a; height = b;
    }
};

class Rectangle : public Polygon {
public:
    int area()
    {
        return width * height;
    }
};

class Triangle : public Polygon {
public:
    int area()
    {
        return width * height / 2;
    }
};

int main() {
    Rectangle rect;
    Triangle trgl;
    Polygon* ppoly1 = &rect;
    Polygon* ppoly2 = &trgl;
    ppoly1->set_values(4, 5);
    ppoly2->set_values(4, 5);
    cout << rect.area() << '\n';
    cout << trgl.area() << '\n';
    return 0;
}

và 1 đoạn code có sử dụng cấp phát động có nội dung là:

#include <iostream>
using namespace std;

class Polygon {
protected:
    int width, height;
public:
    Polygon(int a, int b) : width(a), height(b) {}
    virtual int area(void) = 0;
    void printarea()
    {
        cout << this->area() << '\n';
    }
};

class Rectangle : public Polygon {
public:
    Rectangle(int a, int b) : Polygon(a, b) {}
    int area()
    {
        return width * height;
    }
};

class Triangle : public Polygon {
public:
    Triangle(int a, int b) : Polygon(a, b) {}
    int area()
    {
        return width * height / 2;
    }
};

int main() {
    Polygon* ppoly1 = new Rectangle(4, 5);
    Polygon* ppoly2 = new Triangle(4, 5);
    ppoly1->printarea();
    ppoly2->printarea();
    delete ppoly1;
    delete ppoly2;
    return 0;
}

Em chạy thử và thấy code chạy bình thường dù con trỏ của dạng này nhưng vẫn trỏ tới dạng kia.
Mong các anh chị giải đáp giúp em ạ.

cái này sai rồi, con trỏ thích trỏ tới đâu cũng được cả. Chạy có lỗi hay ko thôi :skull:

con trỏ A* mà trỏ tới đối tượng lớp B, lớp A và lớp B ko liên quan thì chạy có lỗi. Ví dụ int* mà trỏ tới double thì in ra giá trị tầm bậy ko :V

còn nếu A B có liên quan thì ví dụ có thể coi đối tượng a tạo ra từ 1 lớp A có n bytes, địa chỉ của nó trong bộ nhớ là [x, x+n), đối tượng b tạo ra từ lớp con B kế thừa lớp A có thêm b bytes thành n+b bytes, có địa chỉ trong bộ nhớ là [y, y+n+b). Nếu con trỏ A* trỏ tới b ở địa chỉ y thì nó vẫn có thể hiểu b là kiểu lớp A vì [y, y+n) vẫn chứa đầy đủ thuộc tính của lớp A, nên chương trình sẽ chạy đúng. Nhưng nếu con trỏ B* mà trỏ tới a thì vì a chỉ chiếm vùng nhớ từ [x, x+n) nên từ [x+n, x+n+b) ko có giá trị gì, a chỉ có n bytes mà hiểu là đối tượng lớp B có n+b bytes thì chạy sẽ bị lỗi :V

multiple inheritance còn phức tạp hơn nữa, thôi mường tượng sơ sơ vậy cũng được rồi :V

em học vào learncpp.com mà học :V ví dụ chapter 18 nói về đa hình: https://www.learncpp.com/cpp-tutorial/pointers-and-references-to-the-base-class-of-derived-objects/

mà ở trang cplusplus kia họ cũng có ghi mà:

One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class.

trang này cũ lỗi thời chắc 10 năm rồi, tuy mấy kiến thức core này chắc 10 năm trước cũng ko thay đổi gì mấy so với bây giờ nhưng em cứ vào learncpp mà đọc cho nó cập nhật :V

còn nếu rảnhtryhard hơn thì em vào cppreference.com mà tìm. Anh tìm được: https://en.cppreference.com/w/cpp/language/implicit_conversion#Pointer_conversions

A prvalue pointer to a (optionally cv-qualified) derived complete class type can be converted to a prvalue pointer to its (identically cv-qualified) base class. If the base class is inaccessible or ambiguous, the conversion is ill-formed (won’t compile). The result of the conversion is a pointer to the base class subobject within the pointed-to object. The null pointer value is converted to the null pointer value of the destination type.

chuẩn nói là con trỏ lớp con có thể cast ngầm định (implicit conversion) thành con trỏ lớp cha, và con trỏ này trỏ tới subobject nằm trong lớp con đó :V :V Nghĩa là đa kế thừa thì gán A2* a2 = &b với lớp B kế thừa lớp A1, A2 thì có thể giá trị con trỏ a2 sẽ khác giá trị con trỏ &b

4 Likes

Kiến thức của anh uyên thâm thật sự, giải thích cũng dễ hiểu nữa. Em cảm ơn anh ạ. Anh có đang làm mentor khoonh anh.

ko em, em có thắc mắc gì cứ post lên đây (hay vào dnh discord hỏi cho nhanh)

3 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?