Opaque pointer

Last updated

In computer programming, an opaque pointer is a special case of an opaque data type, a data type declared to be a pointer to a record or data structure of some unspecified type.

Contents

Opaque pointers are present in several programming languages including Ada, C, C++, D and Modula-2.

If the language is strongly typed, programs and procedures that have no other information about an opaque pointer type T can still declare variables, arrays, and record fields of type T, assign values of that type, and compare those values for equality. However, they will not be able to de-reference such a pointer, and can only change the object's content by calling some procedure that has the missing information.

Opaque pointers are a way to hide the implementation details of an interface from ordinary clients, so that the implementation may be changed without the need to recompile the modules using it. This benefits the programmer as well since a simple interface can be created, and most details can be hidden in another file. [1] This is important for providing binary code compatibility through different versions of a shared library, for example.

This technique is described in Design Patterns as the Bridge pattern. It is sometimes referred to as " handle classes", [2] the "Pimpl idiom" (for "pointer to implementation idiom"), [3] "Compiler firewall idiom", [4] "d-pointer" or "Cheshire Cat", especially among the C++ community. [2]

Examples

Ada

packageLibrary_InterfaceistypeHandleislimitedprivate;-- Operations...privatetypeHidden_Implementation;-- Defined in the package bodytypeHandleisaccessHidden_Implementation;endLibrary_Interface;

The type Handle is an opaque pointer to the real implementation, that is not defined in the specification. Note that the type is not only private (to forbid the clients from accessing the type directly, and only through the operations), but also limited (to avoid the copy of the data structure, and thus preventing dangling references).

packagebodyLibrary_InterfaceistypeHidden_Implementationisrecord...-- The actual implementation can be anythingend record;-- Definition of the operations...endLibrary_Interface;

These types are sometimes called "Taft types"—named after Tucker Taft, the main designer of Ada 95—because they were introduced in the so-called Taft Amendment to Ada 83. [5]

C

/* obj.h */structobj;/* * The compiler considers struct obj an incomplete type. Incomplete types * can be used in declarations. */size_tobj_size(void);voidobj_setid(structobj*,int);intobj_getid(structobj*);
/* obj.c */#include"obj.h"structobj{intid;};/* * The caller will handle allocation. * Provide the required information only */size_tobj_size(void){returnsizeof(structobj);}voidobj_setid(structobj*o,inti){o->id=i;}intobj_getid(structobj*o){returno->id;}

This example demonstrates a way to achieve the information hiding (encapsulation) aspect of object-oriented programming using the C language. If someone wanted to change the definition of struct obj, it would be unnecessary to recompile any other modules in the program that use the obj.h header file unless the API was also changed. Note that it may be desirable for the functions to check that the passed pointer is not NULL, but such checks have been omitted above for brevity.

C++

/* PublicClass.h */#include<memory>classPublicClass{public:PublicClass();// ConstructorPublicClass(constPublicClass&);// Copy constructorPublicClass(PublicClass&&);// Move constructorPublicClass&operator=(constPublicClass&);// Copy assignment operatorPublicClass&operator=(PublicClass&&);// Move assignment operator~PublicClass();// Destructor// Other operations...private:structCheshireCat;// Not defined herestd::unique_ptr<CheshireCat>d_ptr_;// Opaque pointer};
/* PublicClass.cpp */#include"PublicClass.h"structPublicClass::CheshireCat{inta;intb;};PublicClass::PublicClass():d_ptr_(std::make_unique<CheshireCat>()){// Do nothing.}PublicClass::PublicClass(constPublicClass&other):d_ptr_(std::make_unique<CheshireCat>(*other.d_ptr_)){// Do nothing.}PublicClass::PublicClass(PublicClass&&other)=default;PublicClass&PublicClass::operator=(constPublicClass&other){*d_ptr_=*other.d_ptr_;return*this;}PublicClass&PublicClass::operator=(PublicClass&&)=default;PublicClass::~PublicClass()=default;

The d-pointer pattern is one of the implementations of the opaque pointer. It is commonly used in C++ classes due to its advantages (noted below). A d-pointer is a private data member of the class that points to an instance of a structure. This method allows class declarations to omit private data members, except for the d-pointer itself. [6] As a result,

One side benefit is that compilations are faster because the header file changes less often. Note, possible disadvantage of d-pointer pattern is indirect member access through pointer (e.g., pointer to object in dynamic storage), which is sometimes slower than access to a plain, non-pointer member. The d-pointer is heavily used in the Qt [7] and KDE libraries.

See also

Related Research Articles

In object-oriented and functional programming, an immutable object is an object whose state cannot be modified after it is created. This is in contrast to a mutable object, which can be modified after it is created. In some cases, an object is considered immutable even if some internally used attributes change, but the object's state appears unchanging from an external point of view. For example, an object that uses memoization to cache the results of expensive computations could still be considered an immutable object.

In computer science, a tagged union, also called a variant, variant record, choice type, discriminated union, disjoint union, sum type or coproduct, is a data structure used to hold a value that could take on several different, but fixed, types. Only one of the types can be in use at any one time, and a tag field explicitly indicates which one is in use. It can be thought of as a type that has several "cases", each of which should be handled correctly when that type is manipulated. This is critical in defining recursive datatypes, in which some component of a value may have the same type as the value itself, for example in defining a type for representing trees, where it is necessary to distinguish multi-node subtrees and leaves. Like ordinary unions, tagged unions can save storage by overlapping storage areas for each type, since only one is in use at a time.

The syntax of the C programming language is the set of rules governing writing of software in the C language. It is designed to allow for programs that are extremely terse, have a close relationship with the resulting object code, and yet provide relatively high-level data abstraction. C was the first widely successful high-level language for portable operating-system development.

<span class="mw-page-title-main">Pointer (computer programming)</span> Object which stores memory addresses in a computer program

In computer science, a pointer is an object in many programming languages that stores a memory address. This can be that of another value located in computer memory, or in some cases, that of memory-mapped computer hardware. A pointer references a location in memory, and obtaining the value stored at that location is known as dereferencing the pointer. As an analogy, a page number in a book's index could be considered a pointer to the corresponding page; dereferencing such a pointer would be done by flipping to the page with the given page number and reading the text found on that page. The actual format and content of a pointer variable is dependent on the underlying computer architecture.

In computer programming, a function object is a construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax. Function objects are often called functors.

A function pointer, also called a subroutine pointer or procedure pointer, is a pointer that points to a function. As opposed to referencing a data value, a function pointer points to executable code within memory. Dereferencing the function pointer yields the referenced function, which can be invoked and passed arguments just as in a normal function call. Such an invocation is also known as an "indirect" call, because the function is being invoked indirectly through a variable instead of directly through a fixed identifier or address.

In the C++ programming language, a reference is a simple reference datatype that is less powerful but safer than the pointer type inherited from C. The name C++ reference may cause confusion, as in computer science a reference is a general concept datatype, with pointers and C++ references being specific reference datatype implementations. The definition of a reference in C++ is such that it does not need to exist. It can be implemented as a new name for an existing object.

<span class="mw-page-title-main">Method overriding</span> Language feature in object-oriented programming

Method overriding, in object-oriented programming, is a language feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its superclasses or parent classes. In addition to providing data-driven algorithm-determined parameters across virtual network interfaces, it also allows for a specific type of polymorphism (subtyping). The implementation in the subclass overrides (replaces) the implementation in the superclass by providing a method that has same name, same parameters or signature, and same return type as the method in the parent class. The version of a method that is executed will be determined by the object that is used to invoke it. If an object of a parent class is used to invoke the method, then the version in the parent class will be executed, but if an object of the subclass is used to invoke the method, then the version in the child class will be executed. This helps in preventing problems associated with differential relay analytics which would otherwise rely on a framework in which method overriding might be obviated. Some languages allow a programmer to prevent a method from being overridden.

In computer science, a mutator method is a method used to control changes to a variable. They are also widely known as setter methods. Often a setter is accompanied by a getter, which returns the value of the private member variable.

In some programming languages, const is a type qualifier that indicates that the data is read-only. While this can be used to declare constants, const in the C family of languages differs from similar constructs in other languages in being part of the type, and thus has complicated behavior when combined with pointers, references, composite data types, and type-checking. In other languages, the data is not in a single memory location, but copied at compile time on each use. Languages which utilize it include C, C++, D, JavaScript, Julia, and Rust.

The One Definition Rule (ODR) is an important rule of the C++ programming language that prescribes that classes/structs and non-inline functions cannot have more than one definition in the entire program and template and types cannot have more than one definition by translation unit. It is defined in the ISO C++ Standard 2003, at section 3.2.

In computer science, object composition and object aggregation are closely related ways to combine objects or data types into more complex ones. In conversation the distinction between composition and aggregation is often ignored. Common kinds of compositions are objects used in object-oriented programming, tagged unions, sets, sequences, and various graph structures. Object compositions relate to, but are not the same as, data structures.

In computer programming, the term hooking covers a range of techniques used to alter or augment the behaviour of an operating system, of applications, or of other software components by intercepting function calls or messages or events passed between software components. Code that handles such intercepted function calls, events or messages is called a hook.

A class in C++ is a user-defined type or data structure declared with keyword class that has data and functions as its members whose access is governed by the three access specifiers private, protected or public. By default access to members of a C++ class is private. The private members are not accessible outside the class; they can be accessed only through methods of the class. The public members form an interface to the class and are accessible outside the class.

The C and C++ programming languages are closely related but have many significant differences. C++ began as a fork of an early, pre-standardized C, and was designed to be mostly source-and-link compatible with C compilers of the time. Due to this, development tools for the two languages are often integrated into a single product, with the programmer able to specify C or C++ as their source language.

The curiously recurring template pattern (CRTP) is an idiom, originally in C++, in which a class X derives from a class template instantiation using X itself as a template argument. More generally it is known as F-bound polymorphism, and it is a form of F-bounded quantification.

C++11 is a version of the ISO/IEC 14882 standard for the C++ programming language. C++11 replaced the prior version of the C++ standard, called C++03, and was later replaced by C++14. The name follows the tradition of naming language versions by the publication year of the specification, though it was formerly named C++0x because it was expected to be published before 2010.

C's offsetof macro is an ANSI C library feature found in stddef.h. It evaluates to the offset of a given member within a struct or union type, an expression of type size_t. The offsetof macro takes two parameters, the first being a structure name, and the second being the name of a member within the structure. It cannot be described as a C prototype.

This article describes the syntax of the C# programming language. The features described are compatible with .NET Framework and Mono.

In C++ computer programming, copy elision refers to a compiler optimization technique that eliminates unnecessary copying of objects.

References

  1. Chris McKillop. "Programming Tools Opaque Pointers". QNX Software Systems. Retrieved 2019-01-16.
  2. 1 2 Bruce Eckel (2000). "Chapter 5: Hiding the Implementation". Thinking in C++, Volume 1: Introduction to Standard C++ (2nd ed.). Prentice Hall. ISBN   0-13-979809-9.
  3. Vladimir Batov (2008-01-25). "Making Pimpl Easy". Dr. Dobb's Journal . Retrieved 2008-05-07.
  4. Herb Sutter. The Joy of Pimpls (or, More About the Compiler-Firewall Idiom)
  5. Robert A. Duff (2002-07-29). "Re: What's its name again?". Newsgroup:  comp.lang.ada . Retrieved 2007-10-11.
  6. Using a d-Pointer — Why and how KDE implements opaque pointers
  7. "D-Pointer". Qt wiki. Retrieved 23 Dec 2016.