2008-12-16 37 views
5

Tôi đang triển khai một thư viện toán bằng C++. Thư viện sẽ được biên dịch thành một DLL nên những người sử dụng nó sẽ chỉ cần các tệp tiêu đề các định nghĩa của các lớp.Tham chiếu Đếm trong C++

Người dùng lớp học của tôi sẽ là những người mới sử dụng ngôn ngữ. Tuy nhiên, có một số đối tượng có thể được tham chiếu trong một số phần của chương trình của họ. Vì tôi không mong đợi họ làm việc quản lý bộ nhớ, tôi muốn tự mình làm điều đó. Vì vậy, tôi phải thực hiện đếm tham chiếu (thu gom rác thải không phải là một khả năng).

Tôi muốn làm tài liệu tham khảo mà đếm như minh bạch càng tốt, ví dụ ...

// Define a Bézier curve 
CVecList pts; 
pts.Add(Vector(0,0,0)); 
pts.Add(Vector(0,0,100)); 
pts.Add(Vector(0,100,0)); 
pts.Add(Vector(0,100,100)); 
CCurve* c1 = new CBezier(pts); 

// Define a 3rd order B-Spline curve 
pts.Clear(); 
pts.Add(Vector(0,0,0)); 
pts.Add(Vector(0,200,100)); 
pts.Add(Vector(0,200,200)); 
pts.Add(Vector(0,-200,100)); 
pts.Add(Vector(0,-200,200)); 
pts.Add(Vector(0,0,0)); 
CCurve* c2 = new CBSpline(pts,3); 

// The Bézier curve object must be deleted automatically 
// because the only reference to it has been released 
// Similar to IUnknown::Release() in COM 
c1 = c2; 

Mọi thứ trở nên phức tạp hơn một chút khi tôi xác định đối tượng bề mặt, bởi vì một số bề mặt được xác định theo hai đường cong:

CVecList pts; 
// ... 
CCurve* f = new CBezier(pts); 

pts.Clear(); 
// ... 
CCurve* g = new CBezier(pts); 

// Mixed surface: S(u,v) = (1-v)*f(u) + v*g(u) 
CSurface* s = new CMixed(f,g); 

// There are two references to the first Bézier curve, 
// the first one is f 
// the second one is hidden in a member of CMixed 

// Something similar applies to the second Bézier curve 

tôi nghĩ rằng trọng operator = cho con trỏ có thể giúp:

// This is what I tried, but it's illegal: 
typedef CReferenceCounted* PRC; 
PRC& operator =(PRC& dest, PRC& source) 
{ 
    if (source) 
     source->AddRef(); 
    if (dest) 
     dest->Release(); 
    memcpy(&dest,&source,sizeof(PRC)); 
    return dest; 
} 

... nhưng sau đó tôi thấy rằng operator = không hợp lệ trừ khi nó là thành viên không tĩnh của một lớp.

Có ai có thể giúp tôi không?

+0

http://ootips.org/yonat/4dev/smart-pointers.html – derobert

+0

Tôi đã cố giữ mã mẫu của mình miễn phí, nhưng tôi không thể đưa ra giải pháp khác. Cảm ơn bạn. –

+0

Eduardo bạn có thể chỉnh sửa bài đăng này, chọn mã trong câu hỏi của bạn, sau đó nhấp vào nút có 0 và 1 không? Điều này sẽ áp dụng cú pháp tô sáng cho mã. –

Trả lời

11

Những gì bạn đã cố gắng là quá tải một toán tử cho các loại vô hướng. C++ không cho phép bạn thực hiện điều đó ngoại trừ các liệt kê (bên cạnh điểm mà toán tử = phải là thành viên). Ít nhất một trong các loại phải là loại do người dùng xác định. Vì vậy, những gì bạn muốn làm là để quấn con trỏ thô vào một lớp người dùng định nghĩa, mà quá tải constructor, sao chép constructor, sao chép phân công điều hành và destructor một làm các tài liệu tham khảo tính thích hợp. Đây là một tình huống lý tưởng cho boost::shared_ptr, mà thực hiện chính xác rằng:

boost::shared_ptr<CCurve> c1(new CBezier(pts)); 

Thỏa thuận tương tự với các bề mặt:

CVecList pts; 
// ... 
boost::shared_ptr<CCurve> f(new CBezier(pts)); 

pts.Clear(); 
// ... 
boost::shared_ptr<CCurve> g(new CBezier(pts)); 

// Mixed surface: S(u,v) = (1-v)f(u) + vg(u) 
boost::shared_ptr<CSurface> s(new CMixed(f,g)); 

Carry xung quanh rằng con trỏ thông minh, và nó sẽ tự động quản lý cuộc sống thời gian của chỉ vào đối tượng: Nếu bản sao cuối cùng của con trỏ ra khỏi phạm vi, đối tượng được trỏ tới được giải phóng. shared_ptr được thiết kế để dễ sử dụng. Cố gắng tránh làm việc với các con trỏ thô nhiều nhất có thể. Hãy nhìn vào những gợi ý thông minh, họ sẽ dễ dàng lập trình viên của bạn sống với C++ :)

Sửa: Nếu bạn đang đi để quấn một shared_ptr, bạn có thể làm như vậy bằng cách sử dụng pimpl (xử lý/body) thành ngữ:

+0

Tôi sẽ dpo một cái gì đó như xác định CCurve như CCurved_internal, sau đó typedef CCurve để tăng :: shared_ptr ,,, – BubbaT

+0

Tôi đã cố gắng để giữ mã mẫu của tôi miễn phí, nhưng tôi không thể đến với một giải pháp. Cảm ơn bạn. –

+0

bạn có thể, nếu bạn bọc sử dụng CCurve như không trỏ, và phân bổ tài nguyên bên trong nó. và sau đó CCurve có thể thực hiện đếm tham chiếu, xóa con trỏ được quản lý khi cần. bạn chỉ có thể quấn một shared_ptr, và làm cho nó minh bạch cho học sinh của bạn. –

0

Tôi muốn giới thiệu intrusive_ptr thay vì shared_ptr cho các đối tượng bạn có thể kiểm soát hiệu năng và khả năng sử dụng tốt hơn, vì bạn có thể gán con trỏ thô vào intrusive_ptr sau, vì số tham chiếu được nhúng trong đối tượng.

1

Nếu bạn đang thiết kế một thư viện toán, hãy dành nhiều thời gian để suy nghĩ xem các lớp của bạn có thể trông giống như int hoặc std :: complex hay không. Đó là để nói, có giá trị hành xử giống như giá trị. Ví dụ.

std::vector<math::point3d> pts; 
pts.push_back(math::point3d(0,0,0)); 
pts.push_back(math::point3d(110,0,0)); 
pts.push_back(math::point3d(0,100,0)); 
pts.push_back(math::point3d(0,0,100)); 
CCurve c1 = make_bezier(pts); 
0

Người dùng lớp học của tôi sẽ là những người mới sử dụng ngôn ngữ.

Lớp học của bạn có được thiết kế cho khóa học lập trình không?

Nếu đây là trường hợp, tôi sẽ tránh sử dụng con trỏ và chỉ sử dụng sao chép constructors/gán:

  • Performance/Memory không phải là một ưu tiên
  • Làm công tác quản lý bộ nhớ tự sẽ hiển thị một ví dụ khá xấu về cách sử dụng mới/xóa
  • Sử dụng bất kỳ loại con trỏ thông minh nào mà không biết về quản lý bộ nhớ có thể gây ra nhiều sự nhầm lẫn sau này.
0

Tôi đồng ý với Guishu và MSalters. Ngay cả khi nó không phải là cho một khóa học lập trình, nó có thể được tốt đẹp để bắt chước nhìn toán học chặt chẽ hơn (ví dụ: vector3 = vector1 + vector2 vv).

Điều bạn cũng có thể làm là sử dụng sao chép-ghi-ghi (kể lại là hậu quả logic), nhưng chỉ trong nội bộ. Điều đó có thể cung cấp cho bạn các bài tập đủ nhanh, loại bỏ việc quản lý đống trên phía máy khách và sự tương đồng với ký hiệu toán học.

Lưu ý, tuy nhiên, có các thư viện toán học có sẵn cho C++ (TNT, ngoài đỉnh đầu của tôi). Bạn đã xem xét việc xây dựng công việc của bạn trên đó?

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