Tension between the dependency inversion principle and avoiding “new” in C++?

I have seen a lot of advice that it is better to do Type object; than

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>Type* object = new Type();
</code>
<code>Type* object = new Type(); </code>
Type* object = new Type();

in C++ whenever possible—i.e., minimize your use of new. I understand the rational behind this and appreciate it.

But according to my understanding, to practice dependency inversion requires pointers, e.g.:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>Type* object = new Implementation();
</code>
<code>Type* object = new Implementation(); </code>
Type* object = new Implementation();

where Type is abstract (i.e. contains at least one pure virtual method) and Implementation is concrete. It is not possible to do

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>Type object = Implementation();
</code>
<code>Type object = Implementation(); </code>
Type object = Implementation();

because what that means is

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>Type object;
object = Implementation();
</code>
<code>Type object; object = Implementation(); </code>
Type object;
object = Implementation();

which requires constructing object as a Type initially—but that cannot be done, since Type is abstract.

Is there an inherent tension between the dependency inversion principle and avoiding new when using C++? If so, what patterns/principles/practices can be used to mitigate this tension?

3

You can absolutely use Dependency Injection without ever using new(). Polymorphism, which is what you’re talking about here, is realized in C++ using pointers and/or references. Doc Brown already addressed references, let’s talk about pointers.

As an example (assuming that Implementation is derived from Type, and Bar‘s constructor takes a pointer to a Type):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>Implementation imp;
Bar bar(&imp);
</code>
<code>Implementation imp; Bar bar(&imp); </code>
Implementation imp;
Bar bar(&imp);

The “address of” operator (&) takes the address of an object, the result is a pointer to the object. This is a different way of getting a pointer to an object (different compared to your use of new, that is.)

In C++, any time I have a pointer to a Derived, I can also use it as a pointer to a Base. That’s the whole idea of polymorphism, a Derived is a Base, right?

If my 2-step example above made a leap that you couldn’t follow, I’ll repeat it here, but with one more (unnecessary) step:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>Implementation imp;
Type *t = &imp;
Bar bar(t);
</code>
<code>Implementation imp; Type *t = &imp; Bar bar(t); </code>
Implementation imp;
Type *t = &imp;
Bar bar(t);

t is a pointer to a Type, so it can point to any class derived from Type, including Implementation. No use of new. No tension.

5

DIP means instead of instantiating objects of class Foo directly in class Bar, you have an abstract interface IFoo, and pass already constructed objects of type IFoo into Bar (for example, through the constructor of Bar). That allows you easily to replace Foo objects in Bar by MockFoo objects for example, for testing purposes. If those objects are constructed on the stack like

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> Foo foo;
Bar bar(&foo);
</code>
<code> Foo foo; Bar bar(&foo); </code>
 Foo foo;
 Bar bar(&foo);

or dynamically like

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> IFoo *foo = new Foo();
Bar bar(foo);
</code>
<code> IFoo *foo = new Foo(); Bar bar(foo); </code>
 IFoo *foo = new Foo();
 Bar bar(foo);

where Bar constructor has the signature

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> Bar(IFoo *foo)
{
//...
}
</code>
<code> Bar(IFoo *foo) { //... } </code>
  Bar(IFoo *foo)
  {
       //...
  }

does not matter in terms of DIP, that decision does only depend on the intended life time of your object foo (which in both cases should be at least as long as the lifetime of bar).

The pointer variant is technically different on one aspect: if you like, you can transfer the ownership of the foo object to bar and let bar do the memory cleanup by calling delete on fooin the destructor. However, it is questionable if this is good programming style, and I would not recommend that technique to you. If you want to have automatic cleanup of foo when bar does not need it any more, I suggest that you better make use of smart pointers.

To your edit: I guess you have a misconception here about pointers and “new”. This code

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> Implementation object;
Type *ptrObject = &object;
</code>
<code> Implementation object; Type *ptrObject = &object; </code>
 Implementation object;
 Type *ptrObject = &object;

gives you a pointer to an object of type Type without using new. Or in short:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>"Avoiding the usage of new" != "You cannot have pointers"
</code>
<code>"Avoiding the usage of new" != "You cannot have pointers" </code>
"Avoiding the usage of new" != "You cannot have pointers"

(and both is irrelevant to the dependency inversion principle).

2

No, dependency inversion does not necessitate pointers.

The decision to use pointers or not is a question of data sharing and memory optimization.

Dependency inversion has to do with class hierarchies and inhertiance.

All the same places where you expect to pass Type* that was allocated with new Type() can be changed to accept a Type& that is created with type = Type().

9

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật