• Welcome to the new Internet Infidels Discussion Board, formerly Talk Freethought.

A Successor of C++?

In plain C, one makes a null pointer with 0, and the macro NULL usually expands to 0. But recent C++ also supports "nullptr" for null pointers.

A common use case for null pointers is optional values, and that can be handled in C++ with the "pair" template (tuple with two values). But most recently, the "optional" template has been introduced for supporting optional values.

It has member functions has_value(), value() (throws exception for absent value), and value_or() (uses arg value for absent value).

From the looks of it, C++ is going far from its roots as "C with classes".
I have no problem stepping further from C, in C++, though, insofar as it adds useful structures and standard practices and models.

In fact, you just brought up a way that significantly streamlines requirement-heavy code for when realtime sequential data transformation is necessary (say, you have a piece of data that can be filtered with a series of linear transforms), you can, instead of having hacky solutions like setting floats to NAN for when any value is invalid, simply use these weak pointer-based abstractions to add a natural flag to the data (flagged by pointer-is-null).

This also opens use of NAN testing for when floating point math actually goes tits or divides by zero or whatever.
Or you praoctively test for things like divide by ze before it happens.
In floating point math that leads to a disgusting amount of additional coding, at every point/slope/multiply or difference result. It's a lot more straightforward and logically concise to check if a floating point calculation just didn't give a number as a result, and chain that out as a real result. It gives more visibility on a system wherein states can exist in which both "not calculated" and "calculated as invalid" are useful states, and presents a very concise and "unclever" way to do it.
 
[off-topic] There is one case where C, despite good intentions, "gets it wrong," sort of:
Code:
              int          *xp = 0;
              int*         zp = 0;
              int          *yp;
              yp    = 0;
xp and yp are handled identically in the above fragment but they APPEAR different (*xp=0 vs yp=0). Some avoid confusion by changing the position of white-space as I've shown with zp. My work-around is just to avoid initializers of that form. They have no purpose except to reduce the line-count slightly.
(Nitpick: assigning a 0 to a pointer may generate warnings due to assigning a literal of integral type to a pointer type. The proper way is to assign nullptr or null depending on version.)

I don't think I've ever used a compiler that would give a warning in that case. If I found one I would drag it down to the Trashcan icon ASAP.

And yes, I am aware that there are some implementations where a null pointer is represented internally as something other than all zero bits. Do you know how such a weird case for null pointer is denoted in C source?
0
 
[off-topic] There is one case where C, despite good intentions, "gets it wrong," sort of:
Code:
              int          *xp = 0;
              int*         zp = 0;
              int          *yp;
              yp    = 0;
xp and yp are handled identically in the above fragment but they APPEAR different (*xp=0 vs yp=0). Some avoid confusion by changing the position of white-space as I've shown with zp. My work-around is just to avoid initializers of that form. They have no purpose except to reduce the line-count slightly.
(Nitpick: assigning a 0 to a pointer may generate warnings due to assigning a literal of integral type to a pointer type. The proper way is to assign nullptr or null depending on version.)

I don't think I've ever used a compiler that would give a warning in that case. If I found one I would drag it down to the Trashcan icon ASAP.

And yes, I am aware that there are some implementations where a null pointer is represented internally as something other than all zero bits. Do you know how such a weird case for null pointer is denoted in C source?
0
More, compilers use pointer-to-int vs int typing, where NULL is just 0, but nullptr is cast as pointer-to.
 
@ Steve — You're right about shortcuts for multiple-dimensionaL arrays, but it's better to declare a pointer (as a working register in typical practice) to a 1-D array for your use; this makes the code much more portable and avoids compiler warnings.

If Arr is conceptually a 2-D array, which will be accessed via " Arr[y][x] " it is still possible to declare Arr in four ways:

int Arr[35][80];
int *(Arr[35]);
int (*Arr)[80];
int **Arr;

It should often be possible to process the Arr with code that will need few if any changes if/when the type definition of Arr changes.

I am long out of practice just doodling.

A two dimensional array is stored sequentially. Yo can set a pointer to a multidimensional array and index through it.

Both printings give the same result.

You can find the size of an array by sizeof(array)/sizeof(array[0]) but it does not give you rows and columns, just the libear size in memory.

Not quite. If array is a 2-D array, then " sizeof(array[0] ) " will be — did you guess? — the size of " array[0] ". Thus the macro will return the number of rows in the table, NOT the number of bytes.
My point on pointers was that physical memory is linear.

Sizeof(array[0]) gives you the size in bytes of the data type. Sizeof(array) gives the size of the array in bytes. Sizeof(array)/sizeof(array[0]] gives you the number of entries in the array but not how it is structured in terms of rows and columns.

MY point was that your claim is incorrect IF array is a two- (or more-) dimensional array. You have doubled-down on that error.

Like most of us, I have VAST areas of ignorance. I don't think C coding is one of them.
 
[off-topic] There is one case where C, despite good intentions, "gets it wrong," sort of:
Code:
              int          *xp = 0;
              int*         zp = 0;
              int          *yp;
              yp    = 0;
xp and yp are handled identically in the above fragment but they APPEAR different (*xp=0 vs yp=0). Some avoid confusion by changing the position of white-space as I've shown with zp. My work-around is just to avoid initializers of that form. They have no purpose except to reduce the line-count slightly.

Part of why I say C is half a language.

Yeah, I know that 0 and null are the same thing here.
 
In plain C, one makes a null pointer with 0, and the macro NULL usually expands to 0. But recent C++ also supports "nullptr" for null pointers.

A common use case for null pointers is optional values, and that can be handled in C++ with the "pair" template (tuple with two values). But most recently, the "optional" template has been introduced for supporting optional values.

It has member functions has_value(), value() (throws exception for absent value), and value_or() (uses arg value for absent value).

From the looks of it, C++ is going far from its roots as "C with classes".

value_or sounds like the equivalent of the C# ?? and I find it a very nice feature. Especially since operators can be combined with assignment--this makes lazy initalization expressable as LazyValue ??= CalculateLazyValue(); One simple, obvious statement, anyone looking at it will know exactly what was intended.
 
@ Steve — You're right about shortcuts for multiple-dimensionaL arrays, but it's better to declare a pointer (as a working register in typical practice) to a 1-D array for your use; this makes the code much more portable and avoids compiler warnings.

If Arr is conceptually a 2-D array, which will be accessed via " Arr[y][x] " it is still possible to declare Arr in four ways:

int Arr[35][80];
int *(Arr[35]);
int (*Arr)[80];
int **Arr;

It should often be possible to process the Arr with code that will need few if any changes if/when the type definition of Arr changes.

I am long out of practice just doodling.

A two dimensional array is stored sequentially. Yo can set a pointer to a multidimensional array and index through it.

Both printings give the same result.

You can find the size of an array by sizeof(array)/sizeof(array[0]) but it does not give you rows and columns, just the libear size in memory.

Not quite. If array is a 2-D array, then " sizeof(array[0] ) " will be — did you guess? — the size of " array[0] ". Thus the macro will return the number of rows in the table, NOT the number of bytes.
My point on pointers was that physical memory is linear.

Sizeof(array[0]) gives you the size in bytes of the data type. Sizeof(array) gives the size of the array in bytes. Sizeof(array)/sizeof(array[0]] gives you the number of entries in the array but not how it is structured in terms of rows and columns.

MY point was that your claim is incorrect IF array is a two- (or more-) dimensional array. You have doubled-down on that error.

Like most of us, I have VAST areas of ignorance. I don't think C coding is one of them.
To me the beauty of engineering was something worked or it didn't. Debate was usually a waste pf time.
 
Part of C++ was writing code that was easier to reuse. I did not have use for most of the features.

Inheritance seemed like a feature that if misapplied could led to a complicated mess.

Inheritance is a mechanism of reusing and extending existing classes without modifying them, thus producing hierarchical relationships between them. Inheritance is almost like embedding an object into a class.

Polymorphism in C++ means, the same entity (function or object) behaves differently in different scenarios. Consider this example: The “ +” operator in c++ can perform two specific functions at two different scenarios i.e when the “+” operator is used in numbers, it performs


n normal terms Encapsulation is defined as wrapping up of data and information under a single unit. In Object Oriented Programming, Encapsulation is defined as binding together the data and the functions that manipulates them. Consider a real life example of encapsulation, in a company there are different sections like the accounts section, finance section, sales section etc. The finance section handles all the financial transactions and keep records of all the data related to finance. Similarly the sales section handles all the sales related activities and keep records of all the sales. Now there may arise a situation when for some reason an official from finance section needs all the data about sales in a particular month. In this case, he is not allowed to directly access the data of sales section. He will first have to contact some other officer in the sales section and then request him to give the particular data. This is what encapsulation is. Here the data of sales section and the employees that can manipulate them are wrapped under a single name “sales section”.


We can not access any function from class directly. We need an object to access that function which is using the member the variable of that class.

The function which we are making inside the class ,it must use the all member variable then only it is called encapsulation.

If we don’t make function inside the class which is using the member variable of the class then we don’t call it encapsulation.

Data abstraction is one of the most essential and important feature of object oriented programming in C++. Abstraction means displaying only essential information and hiding the details. Data abstraction refers to providing only essential information about the data to the outside world, hiding the background details or implementation.


Consider a real life example of a man driving a car. The man only knows that pressing the accelerators will increase the speed of car or applying brakes will stop the car but he does not know about how on pressing accelerator the speed is actually increasing, he does not know about the inner mechanism of the car or the implementation of accelerator, brakes etc in the car. This is what abstraction is.

Abstraction using Classes:
We can implement Abstraction in C++ using classes. Class helps us to group data members and member functions using available access specifiers. A Class can decide which data member will be visible to outside world and which is not.

Abstraction in Header files: One more type of abstraction in C++ can be header files. For example, consider the pow() method present in math.h header file. Whenever we need to calculate power of a number, we simply call the function pow() present in the math.h header file and pass the numbers as arguments without knowing the underlying algorithm according to which the function is actually calculating power of numbers.

Abstraction using access specifiers

Access specifiers are the main pillar of implementing abstraction in C++. We can use access specifiers to enforce restrictions on class members. For example:

  • Members declared as public in a class, can be accessed from anywhere in the program.
  • Members declared as private in a class, can be accessed only from within the class. They are not allowed to be accessed from any part of code outside the class.
We can easily implement abstraction using the above two features provided by access specifiers. Say, the members that defines the internal implementation can be marked as private in a class. And the important information needed to be given to the outside world can be marked as public. And these public members can access the private members as they are inside the class.

The definition for C++ I remember is 'melding of data and the functions operating on the data'.

I did make use of late binding. For me data abstraction was the main feature. Actual details of the syntax were not important.
 
@steve_bank inheritance and polymorphism is in fact one of the most powerful aspects of object oriented programming.

It allows a very special form of abstraction wherein things can have contracts enforced on them for dynamic linkage, or wherein general types can be operated on in general ways, in loops, without having to hit switches.

It allows inner levels of inheritance to be drilled into from higher ones in call chains too.

It's just really nice altogether.
 
Or to put it more simply simply in practical terms.


Polymorphism in C++ describes the ability of different objects to be accessed by a common interface.

I can see the utility in that, perhaps a form of reductio ism.
 
Or to put it more simply simply in practical terms.


Polymorphism in C++ describes the ability of different objects to be accessed by a common interface.

I can see the utility in that, perhaps a form of reductio ism.
List<Person*> people();
people.append(new Eunuch());//implements Person type
printf(people.get(0)->sex());//throws...
 
My previous comments about call by {value,reference,name} were confused and confusing. Please ignore them and let me start over.
...
Call by reference is an alternative to using a pointer. So instead of declaring f(int *numptr), you declare f(int &num). To use it, instead of f(&num), you do f(num).
Are you saying it's equivalent to C's call by name, but just uses different syntax?
Yes. Swammerdami, can you point me to any documentation of the difference in plain C between:
  • Call by value
  • Call by name
  • Call by reference

C has exactly ONE call mechanism: Call by value.
C uses call by value for functions and uses call by name for macros. C doesn't have call by reference but you can fake it using pointers. C++ call by reference is not the same as C's call by name; it will give the same results in some situations but not in others. In call by reference, the program figures out the address of the passed argument at the time of the call; in call by name it figures it out whenever it gets used in the body. So if you write:

#define dumb_macro(x) (j = j + 1, x = 0)
j = 1;
dumb_macro(A[j]);

then you're zeroing A[2]. But if you write analogous code in C++ using call by reference, you're zeroing A[1].

How about the weird overloading of C++'s " & " operator? Is there a simple way to transform it into correct C syntax? If so, why bother to have it? If not, what makes it useful? I'll guess the answer to the second question, if any, has something to do with hobbling the programmer's ability to write through pointers. I am happy to code UNHOBBLED, but thanks anyway! :cool:
The difference between call by value of a pointer and call by reference is that with call by reference the compiler guarantees statically that the pointer isn't null. This may allow better optimization, and there are source code checking applications that will use the information to cut down on useless warnings.
 

The C preprocessor is a powerful feature of the C language, but it is very bug-prone, and C++ offers type-safe alternatives to many preprocessor uses, like declared constants, inlined functions, and template functions and classes.

#define SQRT2 1.41421356237310
const double SQRT2 = 1.41421356237310;

#define SQR(x) x*x
template<typename T> inline T SQR(T x) {return x*x}

#define MAX(x,y) x >= y ? x : y
template<typename T> T MAX(T x, T y) {return x >= y ? x : y;}

To be safe, one will want to put parentheses around everything, to avoid misparsing:

#define SQRT2 (1.41421356237310)
#define SQR(x) ((x)*(x))
#define MAX(x,y) ((x) >= (y) ? (x) : (y))

The C++ definitions will also need some work, to avoid copying heavyweight objects and to indicate that they will not change the args:

template<typename T> inline T SQR(const T &x) {return x*x}

template<typename T> T &MAX(const T &x, const T &y) {return x >= y ? x : y;}
 
That's a great point; and it provides an additional answer to Swami's "why bother to have it?" If C++ didn't provide call by reference as "syntactic sugar", programmers would just get it for themselves anyway with #defines, which wouldn't be as safe.
 
In plain C, one makes a null pointer with 0, and the macro NULL usually expands to 0. But recent C++ also supports "nullptr" for null pointers.

A common use case for null pointers is optional values, and that can be handled in C++ with the "pair" template (tuple with two values). But most recently, the "optional" template has been introduced for supporting optional values.

It has member functions has_value(), value() (throws exception for absent value), and value_or() (uses arg value for absent value).

From the looks of it, C++ is going far from its roots as "C with classes".
I have no problem stepping further from C, in C++, though, insofar as it adds useful structures and standard practices and models.

In fact, you just brought up a way that significantly streamlines requirement-heavy code for when realtime sequential data transformation is necessary (say, you have a piece of data that can be filtered with a series of linear transforms), you can, instead of having hacky solutions like setting floats to NAN for when any value is invalid, simply use these weak pointer-based abstractions to add a natural flag to the data (flagged by pointer-is-null).

This also opens use of NAN testing for when floating point math actually goes tits or divides by zero or whatever.
Or you praoctively test for things like divide by ze before it happens.
In floating point math that leads to a disgusting amount of additional coding, at every point/slope/multiply or difference result. It's a lot more straightforward and logically concise to check if a floating point calculation just didn't give a number as a result, and chain that out as a real result. It gives more visibility on a system wherein states can exist in which both "not calculated" and "calculated as invalid" are useful states, and presents a very concise and "unclever" way to do it.
Coding for reliability means adding code to detect fault and make an orderly exit if needed instead of crashing without warning. The difference between coding and coding for others to use long after you have moved on to something else.

It also involves running realistic test cases to try and make the system crash. Software is only as good as the test cases you run. Which is where OOP comes in. Build and test individual objects before system integration.

My major software projects involved computerised manufacturb systems that had to work, be maintainable, and be reliable.
 
@steve_bank inheritance and polymorphism is in fact one of the most powerful aspects of object oriented programming.

It allows a very special form of abstraction wherein things can have contracts enforced on them for dynamic linkage, or wherein general types can be operated on in general ways, in loops, without having to hit switches.

It allows inner levels of inheritance to be drilled into from higher ones in call chains too.

It's just really nice altogether.

Yup. When it first came along I didn't see why it was so hyped--then I realized objects are just callbacks made super-easy. I had implemented my own version of callbacks and thus was overlooking it's real power.
 
Or to put it more simply simply in practical terms.


Polymorphism in C++ describes the ability of different objects to be accessed by a common interface.

I can see the utility in that, perhaps a form of reductio ism.
List<Person*> people();
people.append(new Eunuch());//implements Person type
printf(people.get(0)->sex());//throws...
Why should this throw? Sex() isn't a null. (And does printing a null throw anyway?? I don't think we had exceptions the last time I wrote any C.)
 
Or to put it more simply simply in practical terms.


Polymorphism in C++ describes the ability of different objects to be accessed by a common interface.

I can see the utility in that, perhaps a form of reductio ism.
List<Person*> people();
people.append(new Eunuch());//implements Person type
printf(people.get(0)->sex());//throws...
Why should this throw? Sex() isn't a null. (And does printing a null throw anyway?? I don't think we had exceptions the last time I wrote any C.)
It's a joke. In C++. Think it through.
 
Or to put it more simply simply in practical terms.


Polymorphism in C++ describes the ability of different objects to be accessed by a common interface.

I can see the utility in that, perhaps a form of reductio ism.
It can be very useful when you have a collection of similar but not identical objects. To look at the sort of stuff I deal with:

abstract class Cabinet()
{
int Width;
int Height;
int Depth;
int DoorCount;
}

class BaseCabinet() : Cabinet
{
int ToeKick;
String DoorStyle;
}

class WallCabinet() : Cabinet
{
int Ceiling;
String DoorStyle;
String CrownMolding;
}

class TallCabinet() : Cabinet
{
int ToeKick;
String CrownMolding;
String UpperDoorStyle;
String LowerDoorStyle;
}

(Yes, integers. 32nds of an inch, no floating point issues. In a metric country that would be millimeters.)
 
That's a great point; and it provides an additional answer to Swami's "why bother to have it?" If C++ didn't provide call by reference as "syntactic sugar", programmers would just get it for themselves anyway with #defines, which wouldn't be as safe.
Syntactic sugar generally means it's safer and it means another programmer will understand what's going on more easily. Thus it's a good thing.
 
Back
Top Bottom