Using the c word in class

In simple terms, you just do these:

  1. Write an interface function to convert all the class functions (constructor, destructor, member functions) as pure functions, and encapsulate them as extern "C"{ }
  2. Convert the pointer to the class as pointer to void, and carefully use type-cast wherever you define the «pure functions»
  3. Call the pure functions in the C-code.

For example here is my simple Rectangle class:

/*** Rectangle.h ***/
class Rectangle{
private:
    double length;
    double breadth;
public:
    Rectangle(double iLength, double iBreadth);
    ~Rectangle();
    double getLength();
    double getBreadth();
};

/*** Rectangle.cpp ***/
#include "Rectangle.h"
#include <iostream>
extern "C" {
    Rectangle::Rectangle(double l, double b) {
        this->length = l;
        this->breadth = b;
    }

    Rectangle::~Rectangle() {
        std::cout << "Deleting object of this class Rectangle" << std::endl;
    }

    double Rectangle::getLength() {
        return this->length;
    }

    double Rectangle::getBreadth() {
        return this->breadth;
    }
}

Now here is my interface to convert the class functions to pure functions. Notice how the pointer to the class is handled!

/*** RectangleInterface.h ***/
#ifdef __cplusplus
extern "C" {
#endif
    typedef void * RHandle;
    RHandle create_Rectangle(double l, double b);
    void    free_Rectangle(RHandle);
    double  getLength(RHandle);
    double  getBreadth(RHandle);

#ifdef __cplusplus
}
#endif

/*** RectangleInterface.cpp ***/ 
#include "RectangleInterface.h"
#include "Rectangle.h"
extern "C"
{
    RHandle create_Rectangle(double l, double b){
        return (Rectangle*) new Rectangle(l, b);
    };
    void free_Rectangle(RHandle p){
        delete (Rectangle*) p;
    }
    double getLength(RHandle p){
        return  ((Rectangle*) p)->getLength();
    }
    double getBreadth(RHandle p){
        return ((Rectangle*)p)->getBreadth();
    }
}

Now I can use these interface functions in my «.c» file as shown below. I just have to include the RectangleInterface.h function here, and the rest is taken care by its functions.

/*** Main function call ***/
#include <stdio.h>
#include "RectangleInterface.h"

int main()
{
    printf("Hello World!!n");
    RHandle myRec = create_Rectangle(4, 3);
    printf("The length of the rectangle is %fn", getLength(myRec));
    printf("The area of the rectangle is %fn", (getLength(myRec)*getBreadth(myRec)));
    free_Rectangle(myRec);
    return 0;
}

Some thoughts about class in Australia

During a recent interview, a journalist pulled me up for using the c-word.

Class?” she asked with lifted eyebrow. “What do you mean?”

I found myself chewing the air a moment. Had I said something foul, something embarrassing to both of us? Discussing two of my fictional characters in terms of the social distinctions that separated them, it seemed I’d somehow broached a topic that wasn’t simply awkward, it was provocative. There was a little charge in the atmosphere. I tried not to put it down to the fact that I was talking to an employee of News Corp Australia. The reporter in question is a person of independent mind, and I admire her work, but she is, after all, in the employ of Rupert Murdoch, whose editors and columnists maintain a palace watch on what they like to call “the politics of envy”. A blur of competing thoughts went through my mind. Was she being ironic, or did she really expect me to defend any casual reference to class relations? Was I being paranoid, or was this the kind of clarification necessary in the new cultural dispensation? Did the nation’s drift to the right mean that we all needed to be a lot more careful about our public language, lest we expose ourselves to charges of insufficient revolutionary zeal?

After a mortifying beat or two, I made a clumsy attempt to explain myself, and soon saw that whatever the journalist’s own thoughts were on matters of class, the fact that she’d challenged me on my use of the word meant she’d somehow done her duty. To whom she’d fulfilled this implicit obligation wasn’t immediately clear. Beyond my initial twinge of anxiety I didn’t seriously think she had a proprietor or even an editor in mind when she baulked at the offending word. Afterwards I came to the conclusion that a Fairfax journalist or Radio National presenter might well have posed the same question out of a similar sense of duty. In itself it was, of course, no big thing; it just caught me unawares. All the same, it was a signal of the ways in which something fundamental has changed in our culture. In calling me out over my use of the c-word, the interviewer was merely reflecting the zeitgeist. I should have anticipated it. I’ve been making assumptions about our common outlook that are plainly outdated.


I don’t think it’s an exaggeration to say that citizens in contemporary Australia are now implicitly divided into those who bother and those who don’t. It seems poverty and wealth can no longer be attributed – even in part – to social origins; they are apparently manifestations of character. In the space of two decades, with the gap between rich and poor growing wider, Australians have been trained to remain uncharacteristically silent about the origins of social disparity. This inequity is regularly measured and often reported.

In October, John Martin, the OECD’s former director for employment, labour and social affairs, cited figures that estimated 22% of growth in Australia’s household income between 1980 and 2008 went to the richest 1% of the population. The nation’s new prosperity was unevenly spread in those years. To borrow the former Morgan Stanley global equity analyst Gerard Minack’s phrasing about the situation in the United States, “the rising tide did not lift all boats; it floated a few yachts”. And yet there is a curious reluctance to examine the systemic causes of this inequity. The political economist Frank Stilwell has puzzled over what he calls contemporary “beliefs” around social inequality. Australians’ views range, he says, from outright denial of any disparity to Darwinian acceptance. Many now believe “people get what they deserve”, and to my mind such a response is startling and alien. Structural factors have become too awkward to discuss.

As the nation’s former treasurer Wayne Swan learnt in 2012 when he published an essay in this magazine about the disproportionate influence of the nation’s super-rich, anybody reckless enough to declare class a live issue is likely to be met with howls of derision. According to the new mores, any mention of structural social inequality is tantamount to a declaration of class warfare. Concerns about the distribution of wealth, education and health are difficult to raise in a public forum without needing to beat off the ghost of Stalin. The only form of political correctness that the right will tolerate is the careful elision of class from public discourse, and this troubling discretion has become mainstream. It constitutes an ideological triumph for conservatives that even they must marvel at. Having uttered the c-word in polite company, I felt, for a moment, as if I’d shat in the municipal pool.

Australia’s long tradition of egalitarianism was something people my age learnt about at school. I recall teachers, dowdy folk of indeterminate politics, who spoke of “the fair go” with a reverence they usually only applied to Don Bradman or the myth of Anzac. Australia’s fairness was a source of pride, an article of faith. The nation of my childhood was not classless, however. The social distinctions were palpable and the subject of constant discussion. Where I came from – the raw state-housing suburbs of Perth in the early ’60s – there were definite boundaries and behaviours, many imposed and some internalised. The people I knew identified as working class. Proud and resentful, we were alert to difference, amazed whenever we came upon it. Difference was both provocative and exotic, and one generally cancelled out the negative power of the other. We expressed the casual racism of our time. We played sport with blackfellas but didn’t really socialise. We laughed at the ten-pound Poms with their Coronation Street accents but felt slightly cowed by their stories of great cities and imperial grandeur. The street was full of migrants who’d fled war-ravaged Eastern Europe. Like most of the locals, they worked in factories and on road gangs. They told us kids we were free, and we thought they were telling us something we already knew. As a boy, I believed that Jack was as good as his master. But I understood that Jacks like me always had masters.

I watched my grandfather work until he was in his 70s. Sometimes I carried his Gladstone bag for him. It seemed to signify his dignified position as an ordinary worker who did a decent day’s work for a decent day’s union-won pay. He’d started on the wharves in Geraldton, in Western Australia’s Mid West region, and spent decades as a labourer at the Perth Mint, and though the meekest of men he reserved a sly defiance for his “betters”. He was a union man, but his allegiance was more tribal than ideological. The most memorable thing he ever said to me came when I was 14 or so. Rolling one of his slapdash fags on the verandah of his rented house in sunstruck Belmont, he announced that I should press on with my “eddication”, because “that’s yours for life, and whatever else the bosses can get offa ya, they can’t take what’s there between yer ears”. This was the same man who’d pulled my mother out of school at 15 because there seemed no point in her staying on, the bloke whose sons were sent into apprenticeships without a second thought. Twenty years earlier, his world had been narrower, more constrained, and I’m not sure whether he encouraged me out of regret for curtailing my mother’s dreams or whether he was infected by the new sense of promise that was in the air with the rise of Gough Whitlam.

The summer of that sage moment, all things seemed possible to working people in Australia. It was as if all those Jacks and Jills with masters began to feel a new sense of promise for their children and grandchildren. As an adolescent in this new period of flux, it seemed the frontiers between classes were suddenly more provisional. Some will say class boundaries were always notional, but if they had been as permeable before Whitlam, there was certainly no evidence of it in my family, no sign of it in our street. The lines were fixed. Until the 1970s, young people followed closely in their parents’ footsteps. Not just out of solidarity or emulation, but because to a large extent origin was destiny. The children of tradesfolk became tradesfolk, and the offspring of doctors tended to find themselves in the professions. The Whitlam government didn’t completely bulldoze the walls between classes, but it did knock a few holes in the parapet, and without those liberating gaps my future would have been very different.


Compared to most fields of endeavour, sport and entertainment seem relatively porous in social terms. The arts – which often combine elements of sport and entertainment – are a little like them in this regard, though historically they have always been more class-determined than it’s comfortable to admit. Ask any director at a major theatre company in this country how many of their actors were educated in public schools. They’ll have to have a good hard think. Traditionally the world of letters is similarly class-bound, though it has changed in my decades as a practitioner. In Australia, as elsewhere, it has always been common for members of the gentry to impoverish themselves for the sake of literature, or to at least fall a few pegs into raffish bohemia along the way. Tom Keneally stood out in Australian letters because for a long time he was the most visible exception to the class rule. Hailing from Sydney’s Homebush, a son of working people, Keneally wrote himself, by accident or design, into the bourgeoisie. In his early years, he laboured in the shadow of Patrick White. The great laureate was invariably presented to the world as an oddball, but in truth White’s trajectory embodied the rule. Our purse-lipped Jeremiah was a scion of the squattocracy. His was a life of inherited mobility. He began writing in spats and ended up scowling contentedly in a cardigan and beret, and to that extent he conformed to a pattern very familiar indeed. He was, whether he knew it or not, the norm.

So as a child of the working class who has prospered to a degree unimaginable to my parents and grandparents, and done it in the arts, I am conscious that my own trajectory is atypical. And yet a career like mine is not quite the rarity it would have been a generation ago. My contemporaries Richard Flanagan and Christos Tsiolkas, who also make their living as literary novelists, are but two examples of this slow erosion of the status quo. Both seem to have emerged from what were once termed the lower orders and found themselves – by reason of income and social recognition – in the middle class. I’m not sure how they feel about their new social station, but I am reconciled to mine. In middle age I am conscious of my good fortune and happy to acknowledge that it’s more a manifestation of cultural history than individual talent. My own inheritance was a social tradition. I grew up in a country that codified the dignity of labour, that treasured decency and fairness, where the individual was valued and the collective aspirations of ordinary people were honoured, and I came of age during a social convulsion by which the culture enriched itself in a hectic explosion of hope and innovation. In that sense, I consider myself luckier than any lad born to a fortune in a previous generation.

 I was the first of my family to finish school, the first to complete a tertiary education. Like my younger siblings, I surfed the pent-up force of my parents’ thwarted hopes. They wanted us to have lives that were less subject to the whims of others – the bosses my grandfather spoke of – and they knew that access to education was the key. No one in my family spoke about economics; the future was never about money. What my parents dreamt of was simply a larger, more open existence for their children. Their hopes were rarely expressed in ideological terms. They were not political people and certainly not radicals. Billy Graham inspired them more than the distant and slightly poncy Gough. They urged us to use the gifts we were born with and to refuse to accept the status quo.

We acknowledged class distinctions as facts of life. In high school and university, class was a constant topic of conversation and study. Even at the utopian apogee of my youth I could never have imagined a time when class might be rendered obsolete by history. I certainly never foresaw an age when the very word might hang in the air like something forbidden.


Fifteen years ago, at a book party in London’s Soho, the literary editor of a newspaper, in his cups, suggested I was a bit “chippy”. I was dumbstruck. Even after the fellow was poured into a cab and my amused UK publisher had time to explain the meaning of the term, I remained bewildered. Apparently, at the sort of gentlemen’s club indispensible to British publishing, it was impolite to mention one’s social origins; it made people uncomfortable. Even the most casual, lighthearted reference to class was viewed as “making a song and dance about it”. I was among people who either had been to Oxbridge or were pretending they had. Their accents and manners – even those who’d already begun to speak like Jamie Oliver – were shaped by conceptions of class. As an exotic, I’d had something of a free pass that evening – until I mentioned the c-word. Lesson learnt, I filed that evening’s faux pas under Foreign Customs. Now a similar awkwardness has arisen at home.

In the past few years, some friends have remarked upon my anachronistic class-consciousness. Invariably they’re the children of professionals, graduates of elite schools – all of them lovely, decent people. One, the son of an architect, gave me a blue collar for my 45th birthday. It was funny; I enjoyed the joke, but I wonder what he would’ve had in store had I been a woman and a bit gender-focused, or Aboriginal and a tad race-obsessed.

 If I remain preoccupied with class, it’s not because I’m chippy or resentful. I don’t feel embittered or damaged. I have no hard-luck story to tell. But social distinctions still fascinate me. Perhaps, if I try to take the most disinterested view, their apparent demise has rendered them more compelling; their political invisibility makes them more vivid. But I find it hard to see class dispassionately, because within my family it’s still personal and immediate; it’s still a live issue. I feel it grinding away tectonically in the lives of relatives and friends who may not want to talk about class but who are subject to its force every day.

In 2010, when my face appeared on a postage stamp, I had to submit to the good-humoured sledging of relatives at pains to restrain their pride. In my family, teasing is a blood sport and a measure of affection, so I copped it with pleasure. I enjoyed their refusal to seem impressed. Of course, there were lots of jokes about having to lick the back of my head. But at certain moments it was painful to be reminded that some of them could moisten the stamp but not write the letter it was supposed to send on its way. These are the family members who only follow my stories in audio format – not because they’re too busy to be bothered with books but because they are functionally illiterate. Their curtailed educations, which have sorely constrained their adult lives, were not a manifestation of character. They were outcomes of class. When I’m with those of my friends who are privately educated, I can’t help but be mindful, now and then, of those intimate and often shameful family constraints. Prosperous Australians, even those who’ve snuck under the wire like myself, forget so easily that others are still living over-determined lives in another economy altogether. They aren’t all faceless abstractions, either. Many of them are old neighbours, school friends, relatives, and often they live close by, in the same postcode as you.

When I was young, I didn’t know people like me. By which I mean middle class: comfortable, confident, mobile. I never mixed with people from outside my own socio-economic bracket. There was no opportunity. And it seemed there was no need. I didn’t know anyone who went to a private school. The Catholic kids across the street went to the convent, but that was a step down from state school. It wasn’t until I went to the Western Australian Institute of Technology, now Curtin University, that I came into contact with people my age who’d had private educations. If Whitlam hadn’t abolished tertiary education fees in 1974, I doubt I would have made it to university at all. My parents certainly couldn’t have afforded full tuition, and if there were scholarships available to bright young oiks back then we didn’t know about them. Like so many others of my generation, as the first of a family to enter university I was an outrider on a strange and wonderful frontier. All of us were changed as a result. It expanded the curtailed and tribal world of my immediate family – exploded it forever.

“The Uni”, as my parents called it, was a revelation. The campus of the 1970s was a circus. Everywhere you looked there was a performance, an inversion, a spectacle. It was liberating and surreal. Imperious daughters of the gentry experimented with meekness. Rough-knuckled boys slowly came out as gay. Confused by all the costume and panto, some of us began shyly to ask one another about our backgrounds. For many, the schools we’d come from had given us a certain confidence that only applied within tribal boundaries. Even the posh kids were wrong-footed by the new rules. We were all at sea, only revealing ourselves in cautious increments. We looked wistfully to our new teachers as they strolled the corridors with remarkable aplomb. The tenured Marxists in liberal arts courses were not the first bourgeois citizens I ever encountered, but they were the first I spent significant time with. Their self-assurance was epic, marvellous, dizzying. Some of them took modish intellectual positions and had delusional self-hating politics, but what was most intriguing about them was not the choices they made but the fact that they’d had so many choices to make. Range of choice, I discovered, was a key indicator of class. Some choices are conferred by birth, while others have to be won by hard work. A few can only be achieved by legislation.

I didn’t miss the determined certainties of being working class. Nor did I miss its self-limiting tribalism. But I probably wasn’t prepared for the growing self-interest of the class I gradually joined. For if there’s solidarity at work anywhere in our society these days it’s among the very rich, and the middle class has watched and learnt. Middle Australia is increasingly class-conscious, and it looks to bolster its interests at every turn.


Once the old class-based educational barriers had been down for a decade, Australia seemed to have broadened somewhat. By the 1980s the old working class was harder to identify. Manufacturing was on the wane, but tradespeople began to earn incomes that were once the preserve of the middle class. It was confusing, even upsetting, for some older Australians to learn that a plumber might earn more than a teacher. This was well before the minerals boom that has enabled a bus driver in the Pilbara to pull down the salary of a doctor in Hobart.

Despite all these changes, class never disappeared from cultural consciousness. Surprisingly, it wasn’t the poor and overlooked who resorted to class discourse. The union movement that had once given voice and language to class struggle had been smashed or had imploded. Margaret Thatcher declared there was no such thing as society, and Australian governments gradually internalised that view and appropriated policies that sprang from it. Governments of both major parties oversaw a transition from collective citizenship to consumer individualism that remade our conceptions of taxation, health and education. Federal ministers – Labor and Liberal – who’d been educated in the era of Whitlam promptly pulled the ladder up after themselves. It was pay-as-you-go for my kids. Or graduate in debt. Workers were encouraged to see themselves as contractors, employers as entrepreneurs. Looking back, it seems now like something of a counter-reformation, an ugly regression. But it hasn’t been the vanquished workers pressing the language of class warfare into service. It’s the growing middle class.

The success of Middle Australia hadn’t brought the confidence you’d expect. By the turn of the century, these prospering folk seemed defensive, even a little besieged, and the class basis of much of their social discourse was either unacknowledged or completely unconscious. The boho-bourgeois inner city has long been plagued by smugness, something the suburban middle class might aspire to if only it weren’t so anxious. It takes a deep level of entitlement to be that smug. Middle Australia settled for just being fractious and snooty. Only in the past decade did we begin to hear successful tradespeople being called “cashed-up bogans”. What else could that signify but class anxiety? Very quickly, a large cohort of middle-class people found a means of codifying contempt for those rough-handed interlopers who’d been elevated by the minerals boom into Middle Australia without the benefit of the social conventions and tastes the old middle class was born to. What was the source of all this anxiety? That Jack might leapfrog his masters and give them the finger in passing. That they, Robert Menzies’ “forgotten people”, might be overtaken by the lower orders.

 When I was a kid, most people in the suburbs were likely to describe themselves as battlers – code for unpretentious, working-class toilers. Nowadays, largely as a result of the nation’s remarkable prosperity, the social centre has broadened to the degree that “Middle Australia” is normative. People are just as likely to describe themselves as battlers, but their historically large incomes belie the nature of their struggle, which often has more to do with material ambition than any issue of real hardship. In many instances, the “battles” of Middle Australia are self-imposed. But in recent years they have been valorised and pandered to. At no time was this more obvious than during the Howard years, when the term “Howard’s battlers” was deployed as a deliberate attempt to appropriate the power of class language while simultaneously declaring class a dead issue. Once it was rebadged, the middle class that the conservatives had first courted and then ennobled felt increasingly emboldened to expect greater patronage, extra tax cuts, more concessions, a larger slice of the welfare pie. As a result, subsequent governments have been forced to contend with a middle class that has an increasing sense of entitlement to welfare. And these funds were duly disbursed – largely at the expense of the poor, the sick and the unemployed. This, of course, was the real politics of envy at work. John Howard exploited middle-class resentment of the so-called welfare class and pandered to a sense of victimhood in Middle Australia that Kevin Rudd and Julia Gillard either couldn’t refuse or wouldn’t see. Battlers morphed into “working families” as prospering Australians were taught to minimise their good fortune and expect more state aid. From the subsidisation of private schools to the tax rules favouring the superannuation prospects of the already comfortable, this is the new welfare paradigm. Evidence of it was everywhere before the recent federal election as single mothers were stripped of benefits and middle-class parents who earnt up to $150,000 a year were promised a full wage for six months to stay home and look after their own children.

 As the Sydney Morning Herald’s economics editor Ross Gittins wrote in the lead-up to the September poll, “If you think the class war is over, you’re not paying enough attention.” He said: “The reason the well-off come down so hard on those who use class rhetoric is that they don’t want anyone drawing attention to how the war is going.” To suggest that ours is a classless society or that matters of class are resolved because of national prosperity and the ideological victory of the right is either tin-eared or dishonest. At least the Americans are brutally frank about it. Gittins went on to quote the billionaire investor Warren Buffett, who declared: “There’s class warfare alright, but it’s my class, the rich class, that’s making war, and we’re winning.”


Australia may be dazzlingly prosperous, and keen to project a classless image to itself and others, but it is still socially stratified, even if there are fewer obvious indicators of class distinction than there were 40 years ago. Accent surely isn’t one of them. Postcode can be telling but not conclusive. Even job description can be unreliable. In an era of lax credit regimes, what people wear or drive is misleading, as is the size of the homes they live in. The world of surfaces has never been trickier to read. People have begun to live more ostentatiously, projecting social aspirations that owe more to the entertainment industry than political ideology. The soundest measure of a person’s social status is mobility. And the chief source of mobility is money. Whether you’re born to it or accumulate it, wealth determines a citizen’s choices of education, housing, health care and employment. It will be an indicator of health, of longevity. Money still talks loudest. Even if it often speaks from the corner of its mouth. Even if it covers its mouth entirely. And governments no longer have a taste for the redistribution of wealth. Nor are they keen on intervening to open enclaves and break down barriers to social mobility. Apparently these tasks are the responsibility of the individual.

 Where once Australia looked like a pyramid in terms of its social strata, with the working class as its broad base and ballast and the rich at the top, it’s come to resemble something of a misshapen diamond – wide in the middle – and that’s no bad thing in and of itself. I say that, of course, as a member of the emblematically widening middle. The problem is those Australians the middle has left behind without a glance.

At the bottom, of course, there are the poor, who make up almost 13 per cent of Australia’s population. The most visible of them will always be the welfare class: the sick, the addicted, the impaired and the unemployed, who only exist in the public mind as fodder for tabloid TV and the flagellants of brute radio. But if ever there was a truly “forgotten people” in our time it must be the working poor. These folk, the cleaners and carers and hospitality workers, excite no media outrage. They labour in the shadows in increasingly contingent working situations. Described as “casuals”, the only casual element of their existence is the attitude of the entities that employ them. Often on perpetual call or split shifts, their working lives are unstable. Many of them women, a significant proportion of them migrants, they have little bargaining power and low rates of union representation. As Helen Masterman-Smith and Barbara Pocock vividly document in their 2008 study, Living Low Paid, these people work in hospitals, supermarkets and five-star hotels. They mind the children of prosperous professional couples and wash their incontinent parents in care for an hourly rate most middle-class teenage babysitters can afford to turn their noses up at. It is upon these citizens’ low pay and insecurity that the prosperity of safer families is often built.

 For these vulnerable Australians, there is little mobility. And precious little of what mobility affords – namely, confidence. The cockiness that irritates the old middle class when they encounter fly-in, fly-out workers with their Holden SS utes and tatts and jetskis is rare among the labouring poor. For years I worked in a residential high-rise where the looks on people’s faces in the lifts and on the walkways ranged from wry resignation to unspeakable entrapment. Single mothers on shrinking benefits, injured workers on disability allowances, middle-aged people stocking supermarket shelves at night. Even the most functional and optimistic of them seemed tired. They were not exhausted from partying, from keeping up with all their dizzying choices; they were worn out from simply hanging on and making do. As an accidental tourist in their lives, I was struck by this weariness. And I felt awkward in their presence. Their faces and voices were completely familiar. They smelt like the people of my boyhood – fags, sugar and the beefy whiff of free-range armpit – but despite the cheerful, non-committal conversations we had on our slow ascents in the lift, I felt a distance that took many months to come to terms with. Like the expatriate whose view of home is largely antique, I was a class traveller who’d become a stranger to his own. For all my connection to family, for all the decades I’d spent in fishing towns among tradespeople and labourers, the working class I knew was no more. My new neighbours were living another life entirely.

The sociologist Zygmunt Bauman writes about the contrast between the “light, sprightly and volatile” working lives of mobile citizens at the top of society and those who are largely without choice and prospects. Comfortable, confident people, heirs of the new individualism, often view strangers in cohorts below them in astoundingly superficial terms, as if they have adopted a look, chosen an identity as they often do themselves, as if life were a largely sartorial affair. Faced with your own surfeit of choices, it’s easy to assume everyone has so many. The “liquid” elite understands exotic poverty – it rallies to it tearfully – but it often fails to recognise domestic hardship: poverty of choice, poverty born of constraint, the poverty that is working servitude or the bonded shame of unemployment. Despite the angelic appeal of market thinking, there is no gainsaying the correlation between success and certain family backgrounds, geographical locations, ethnicities and schools. Pretending otherwise isn’t simply dishonest, it’s morally corrosive.

The culture that formed me was poorer, flatter and probably fairer than the one I live in today. Class was more visible, less confusing, more honestly defined and clearly understood. And it was something you could discuss without feeling like a heretic. The decency of our society used to be the measure of its success. Such decency rescued many of us from over-determined lives. It was the moral force that eroded barriers between people, opened up pathways previously unimagined. Not only did it enlarge our personal imaginations but it also enhanced our collective experience. The new cultural confidence this reform produced prefigured the material prosperity we currently enjoy. It was government intervention as much as the so-called genius of the market that underpinned our current prosperity, and it amazes me how quickly we’ve let ourselves be persuaded otherwise.

I have no illusions about overcoming class distinctions completely. Nor am I discounting the role that character plays in an individual’s fortunes. But it disturbs me to see governments abandoning those at the bottom while pandering to the appetites of the comfortable. Under such conditions, what chance is there for the working poor to fight their way free to share in the spoils of our common wealth? No one’s talking ideology. There is no insurrection brewing. For many Australian families, a gap in the fence is all the revolution they require. But while business prospers from the increased casualisation of its workforce, and government continues to reward the insatiable middle, the prospects of help for the weakest and decency for all seem dim indeed.

Tim Winton

Tim Winton is a writer. His most recent novel is The Shepherd’s Hut.

The code is as follows:


using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Office.Interop.Word;
using System.IO;
using System.Web;
using System.Data;
using System.Reflection;
using Microsoft.Win32;
using System.Text.RegularExpressions;
using System.Net;
namespace OfficeOperate
{
    public class WordOperate
    {
        #region  Dynamically generated Word Document and populate the data 
        /**//// <summary>
        ///  Dynamically generated Word Document and populate the data 
        /// </summary>
        /// <returns> Returns custom information </returns>
        public static string CreateWordFile()
        {
            string message = "";
            try
            {
                Object oMissing = System.Reflection.Missing.Value;
                string dir = System.Web.HttpContext.Current.Server.MapPath( "" );// First add in the class library using System.web A reference to the 
                if( !Directory.Exists( dir + "//file" ) )
                {
                    Directory.CreateDirectory( dir + "//file" );  // Create the directory where the files are located 
                }
                string name = DateTime.Now.ToLongDateString() + ".doc";
                object filename = dir + "//file//" + name;  // File save path 
                // create Word The document 
                Microsoft.Office.Interop.Word.Application WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
                Microsoft.Office.Interop.Word.Document WordDoc = WordApp.Documents.Add( ref oMissing, ref oMissing, ref oMissing, ref oMissing );
                /**///// Add the header method 1 : 
                //WordApp.ActiveWindow.View.Type = WdViewType.wdOutlineView;
                //WordApp.ActiveWindow.View.SeekView = WdSeekView.wdSeekPrimaryHeader;
                //WordApp.ActiveWindow.ActivePane.Selection.InsertAfter( " Wuxi quanzhentong technology co. LTD " );// The header content 
                // Add the header method 2 : 
                if( WordApp.ActiveWindow.ActivePane.View.Type == Microsoft.Office.Interop.Word.WdViewType.wdNormalView || WordApp.ActiveWindow.ActivePane.View.Type == Microsoft.Office.Interop.Word.WdViewType.wdOutlineView )
                {
                    WordApp.ActiveWindow.ActivePane.View.Type = Microsoft.Office.Interop.Word.WdViewType.wdPrintView;
                }
                WordApp.ActiveWindow.View.SeekView = Microsoft.Office.Interop.Word.WdSeekView.wdSeekCurrentPageHeader;
                string sHeader = " The header content ";
                WordApp.Selection.HeaderFooter.LinkToPrevious = false;
                WordApp.Selection.HeaderFooter.Range.Text = sHeader;
                WordApp.ActiveWindow.View.SeekView = Microsoft.Office.Interop.Word.WdSeekView.wdSeekMainDocument;
                //WordApp.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphRight;// Right align 
                WordApp.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphLeft;// Left aligned   
                WordApp.ActiveWindow.View.SeekView = WdSeekView.wdSeekMainDocument;// Pops out of the header Settings 
                WordApp.Selection.ParagraphFormat.LineSpacing = 15f;// Sets the line spacing of the document 
                // Move focus and wrap 
                object count = 14;
                object WdLine = Microsoft.Office.Interop.Word.WdUnits.wdLine;// in 1 line ;
                WordApp.Selection.MoveDown( ref WdLine, ref count, ref oMissing );// Move the focus 
                WordApp.Selection.TypeParagraph();// Insert a paragraph 
                // Create a table in the document 
                Microsoft.Office.Interop.Word.Table newTable = WordDoc.Tables.Add( WordApp.Selection.Range, 12, 3, ref oMissing, ref oMissing );
                // Set the table style 
                newTable.Borders.OutsideLineStyle = Microsoft.Office.Interop.Word.WdLineStyle.wdLineStyleThickThinLargeGap;
                newTable.Borders.InsideLineStyle = Microsoft.Office.Interop.Word.WdLineStyle.wdLineStyleSingle;
                newTable.Columns[1].Width = 100f;
                newTable.Columns[2].Width = 220f;
                newTable.Columns[3].Width = 105f;
                // Fill in the table 
                newTable.Cell( 1, 1 ).Range.Text = " Product details table ";
                newTable.Cell( 1, 1 ).Range.Bold = 2;// Set the font in the cell to bold 
                // Merge cell 
                newTable.Cell( 1, 1 ).Merge( newTable.Cell( 1, 3 ) );
                WordApp.Selection.Cells.VerticalAlignment = Microsoft.Office.Interop.Word.WdCellVerticalAlignment.wdCellAlignVerticalCenter;// Vertical center 
                WordApp.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphCenter;// Horizontal center 
                // Fill in the table 
                newTable.Cell( 2, 1 ).Range.Text = " Basic product information ";
                newTable.Cell( 2, 1 ).Range.Font.Color = Microsoft.Office.Interop.Word.WdColor.wdColorDarkBlue;// Sets the font color in the cell 
                // Merge cell 
                newTable.Cell( 2, 1 ).Merge( newTable.Cell( 2, 3 ) );
                WordApp.Selection.Cells.VerticalAlignment = Microsoft.Office.Interop.Word.WdCellVerticalAlignment.wdCellAlignVerticalCenter;
                // Fill in the table 
                newTable.Cell( 3, 1 ).Range.Text = " Brand name: ";
                newTable.Cell( 3, 2 ).Range.Text = "BrandName";
                // Vertically merge the cells 
                newTable.Cell( 3, 3 ).Select();// The selected 1 line 
                object moveUnit = Microsoft.Office.Interop.Word.WdUnits.wdLine;
                object moveCount = 5;
                object moveExtend = Microsoft.Office.Interop.Word.WdMovementType.wdExtend;
                WordApp.Selection.MoveDown( ref moveUnit, ref moveCount, ref moveExtend );
                WordApp.Selection.Cells.Merge();
                // Insert the picture 
                if( File.Exists( System.Web.HttpContext.Current.Server.MapPath( "images//picture.jpg" ) ) )
                {
                    string FileName = System.Web.HttpContext.Current.Server.MapPath( "images//picture.jpg" );// The path of the image 
                    object LinkToFile = false;
                    object SaveWithDocument = true;
                    object Anchor = WordDoc.Application.Selection.Range;
                    WordDoc.Application.ActiveDocument.InlineShapes.AddPicture( FileName, ref LinkToFile, ref SaveWithDocument, ref Anchor );
                    WordDoc.Application.ActiveDocument.InlineShapes[1].Width = 100f;// Image width 
                    WordDoc.Application.ActiveDocument.InlineShapes[1].Height = 100f;// Picture height 
                }
                // Set the image to 4 Weeks surround type 
                Microsoft.Office.Interop.Word.Shape s = WordDoc.Application.ActiveDocument.InlineShapes[1].ConvertToShape();
                s.WrapFormat.Type = Microsoft.Office.Interop.Word.WdWrapType.wdWrapSquare;
                newTable.Cell( 12, 1 ).Range.Text = " Product specific attributes ";
                newTable.Cell( 12, 1 ).Merge( newTable.Cell( 12, 3 ) );
                // Add rows to the table 
                WordDoc.Content.Tables[1].Rows.Add( ref oMissing );
                WordDoc.Paragraphs.Last.Range.Text = " Document creation time: " + DateTime.Now.ToString();// "Signature" 
                WordDoc.Paragraphs.Last.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphRight;
                // file 
                WordDoc.SaveAs( ref filename, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing );
                WordDoc.Close( ref oMissing, ref oMissing, ref oMissing );
                WordApp.Quit( ref oMissing, ref oMissing, ref oMissing );
                message = name + " Document generation successful ";
            }
            catch
            {
                message = " File export exception! ";
            }
            return message;
        }
        #endregion       
        #region  Create and open 1 empty word Edit the document 
        /**//// <summary>
        ///  Create and open 1 empty word Edit the document 
        /// </summary>
        public static void OpenNewWordFileToEdit()
        {
            object oMissing = System.Reflection.Missing.Value;
            Microsoft.Office.Interop.Word.Application WordApp;
            Microsoft.Office.Interop.Word.Document WordDoc;
            WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            WordApp.Visible = true;
            WordDoc = WordApp.Documents.Add( ref oMissing, ref oMissing, ref oMissing, ref oMissing );
        }
        #endregion
        #region  create word The document 
        /**//// <summary>
        ///  create word The document 
        /// </summary>
        /// <returns></returns>
        public static string createWord()
        {
            Microsoft.Office.Interop.Word.Application WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            Document WordDoc;
            string strContent = "";
            object strFileName = System.Web.HttpContext.Current.Server.MapPath( "test.doc " );
            if( System.IO.File.Exists( (string)strFileName ) )
                System.IO.File.Delete( (string)strFileName );
            Object oMissing = System.Reflection.Missing.Value;
            WordDoc = WordApp.Documents.Add( ref oMissing, ref oMissing, ref oMissing, ref oMissing );
            #region    Writes the read-get data from the database to word In the file 
            strContent = " hello /n/n/r ";
            WordDoc.Paragraphs.Last.Range.Text = strContent;
            strContent = " This is the test procedure  ";
            WordDoc.Paragraphs.Last.Range.Text = strContent;
            #endregion
            // will WordDoc The content of the document object is saved as DOC The document   
            WordDoc.SaveAs( ref strFileName, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref   oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing );
            // Shut down WordDoc The document object   
            WordDoc.Close( ref oMissing, ref oMissing, ref oMissing );
            // Shut down WordApp Component object   
            WordApp.Quit( ref oMissing, ref oMissing, ref oMissing );
            string message = strFileName + "/r/n " + " Creating a successful  ";
            return message;
        }
        #endregion
        #region  the Word Document as Html file 
        /**//// <summary>
        ///  the Word Document as Html file 
        /// </summary>
        /// <param name="strFileName"> To convert Word The document </param>
        public static void WordToHtml( string strFileName )
        {
            string saveFileName = strFileName + DateTime.Now.ToString( "yyyy-MM-dd-HH-mm-ss" ) + ".html";
            WordToHtml( strFileName, saveFileName );
        }
        /**//// <summary>
        ///  the Word Document as Html file 
        /// </summary>
        /// <param name="strFileName"> To convert Word The document </param>
        /// <param name="strSaveFileName"> The concrete to be generated Html page </param>
        public static void WordToHtml( string strFileName, string strSaveFileName )
        {
            Microsoft.Office.Interop.Word.ApplicationClass WordApp;
            Microsoft.Office.Interop.Word.Document WordDoc;
            Object oMissing = System.Reflection.Missing.Value;
            WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            object fileName = strFileName;

            WordDoc = WordApp.Documents.Open( ref fileName,
               ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
               ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
               ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing );
            Type wordType = WordApp.GetType();
            //  Open the file 
            Type docsType = WordApp.Documents.GetType();
            //  Convert the format and save as 
            Type docType = WordDoc.GetType();
            object saveFileName = strSaveFileName;
            docType.InvokeMember( "SaveAs", System.Reflection.BindingFlags.InvokeMethod, null, WordDoc, new object[] { saveFileName, Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatHTML } );
            #region  Other formats: 
            /**//**/
            /**////wdFormatHTML
            ///wdFormatDocument
            ///wdFormatDOSText
            ///wdFormatDOSTextLineBreaks
            ///wdFormatEncodedText
            ///wdFormatRTF
            ///wdFormatTemplate
            ///wdFormatText
            ///wdFormatTextLineBreaks
            ///wdFormatUnicodeText
            //--------------------------------------------------------------------------            //            docType.InvokeMember( "SaveAs", System.Reflection.BindingFlags.InvokeMethod,
            //                null, WordDoc, new object[]{saveFileName, Word.WdSaveFormat.wdFormatHTML} );
            //  exit  Word
            //wordType.InvokeMember( "Quit", System.Reflection.BindingFlags.InvokeMethod,
            //    null, WordApp, null );
            #endregion
            WordDoc.Close( ref oMissing, ref oMissing, ref oMissing );
            WordApp.Quit( ref oMissing, ref oMissing, ref oMissing );
        }
        #endregion
        #region  Import the template 
        /**//// <summary>
        ///  Import the template 
        /// </summary>
        /// <param name="filePath"> Template document path </param>
        public static void ImportTemplate( string filePath )
        {
            object oMissing = System.Reflection.Missing.Value;
            Microsoft.Office.Interop.Word.Application WordApp;
            Microsoft.Office.Interop.Word.Document WordDoc;
            WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            WordApp.Visible = true;
            object fileName = filePath;
            WordDoc = WordApp.Documents.Add( ref fileName, ref oMissing, ref oMissing, ref oMissing );
        }
        #endregion
        #region word Add a new table in 
        /**//// <summary>
        /// word Add a new table in 
        /// </summary>
        public static void AddTable()
        {
            object oMissing = System.Reflection.Missing.Value;
            Microsoft.Office.Interop.Word.Application WordApp;
            Microsoft.Office.Interop.Word.Document WordDoc;
            WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            WordApp.Visible = true;
            WordDoc = WordApp.Documents.Add( ref oMissing, ref oMissing, ref oMissing, ref oMissing );
            object start = 0;
            object end = 0;
            Microsoft.Office.Interop.Word.Range tableLocation = WordDoc.Range( ref start, ref end );
            WordDoc.Tables.Add( tableLocation, 3, 4, ref oMissing, ref oMissing );//3 line 4 Column of the table 
        }
        #endregion
        #region  Insert a new row into the table 
        /**//// <summary>
        ///  Insert a new one into the table 1 line 
        /// </summary>
        public static void AddRow()
        {
            object oMissing = System.Reflection.Missing.Value;
            Microsoft.Office.Interop.Word.Application WordApp;
            Microsoft.Office.Interop.Word.Document WordDoc;
            WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            WordApp.Visible = true;
            WordDoc = WordApp.Documents.Add( ref oMissing, ref oMissing, ref oMissing, ref oMissing );
            object start = 0;
            object end = 0;
            Microsoft.Office.Interop.Word.Range tableLocation = WordDoc.Range( ref start, ref end );
            WordDoc.Tables.Add( tableLocation, 3, 4, ref oMissing, ref oMissing );
            Microsoft.Office.Interop.Word.Table newTable = WordDoc.Tables[1];
            object beforeRow = newTable.Rows[1];
            newTable.Rows.Add( ref beforeRow );
        }
        #endregion
        #region  Split cell 
        /**//// <summary>
        ///  Merge cell 
        /// </summary>
        public static void CombinationCell()
        {
            object oMissing = System.Reflection.Missing.Value;
            Microsoft.Office.Interop.Word.Application WordApp;
            Microsoft.Office.Interop.Word.Document WordDoc;
            WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            WordApp.Visible = true;
            WordDoc = WordApp.Documents.Add( ref oMissing, ref oMissing, ref oMissing, ref oMissing );
            object start = 0;
            object end = 0;
            Microsoft.Office.Interop.Word.Range tableLocation = WordDoc.Range( ref start, ref end );
            WordDoc.Tables.Add( tableLocation, 3, 4, ref oMissing, ref oMissing );
            Microsoft.Office.Interop.Word.Table newTable = WordDoc.Tables[1];
            object beforeRow = newTable.Rows[1];
            newTable.Rows.Add( ref beforeRow );
            Microsoft.Office.Interop.Word.Cell cell = newTable.Cell( 2, 1 );//2 line 1 columns 2 line 2 As a 1 since 
            cell.Merge( newTable.Cell( 2, 2 ) );
            //cell.Merge( newTable.Cell( 1, 3 ) );
        }
        #endregion
        #region  Split cell 
        /**//// <summary>
        ///  Split cell 
        /// </summary>
        public static void SeparateCell()
        {
            object oMissing = System.Reflection.Missing.Value;
            Microsoft.Office.Interop.Word.Application WordApp;
            Microsoft.Office.Interop.Word.Document WordDoc;
            WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            WordApp.Visible = true;
            WordDoc = WordApp.Documents.Add( ref oMissing, ref oMissing, ref oMissing, ref oMissing );
            object start = 0;
            object end = 0;
            Microsoft.Office.Interop.Word.Range tableLocation = WordDoc.Range( ref start, ref end );
            WordDoc.Tables.Add( tableLocation, 3, 4, ref oMissing, ref oMissing );
            Microsoft.Office.Interop.Word.Table newTable = WordDoc.Tables[1];
            object beforeRow = newTable.Rows[1];
            newTable.Rows.Add( ref beforeRow );
            Microsoft.Office.Interop.Word.Cell cell = newTable.Cell( 1, 1 );
            cell.Merge( newTable.Cell( 1, 2 ) );
            object Rownum = 2;
            object Columnnum = 2;
            cell.Split( ref Rownum, ref  Columnnum );
        }
        #endregion
        #region  The insertion is controlled by paragraphs Insert a paragraph at the beginning of the document.
        /**//// <summary>
        ///  The insertion is controlled by paragraphs Insert a paragraph at the beginning of the document.
        /// </summary>
        public static void Insert()
        {
            object oMissing = System.Reflection.Missing.Value;
            //object oEndOfDoc = "//endofdoc"; /**//* /endofdoc is a predefined bookmark */
            //Start Word and create a new document.
            Microsoft.Office.Interop.Word.Application WordApp;
            Microsoft.Office.Interop.Word.Document WordDoc;
            WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            WordApp.Visible = true;
            WordDoc = WordApp.Documents.Add( ref oMissing, ref oMissing, ref oMissing, ref oMissing );
            //Insert a paragraph at the beginning of the document.
            Microsoft.Office.Interop.Word.Paragraph oPara1;
            oPara1 = WordDoc.Content.Paragraphs.Add( ref oMissing );
            oPara1.Range.Text = "Heading 1";
            oPara1.Range.Font.Bold = 1;
            oPara1.Format.SpaceAfter = 24;    //24 pt spacing after paragraph.
            oPara1.Range.InsertParagraphAfter();
        }
        #endregion
        #region word Document Settings and gets cursor position 
        /**//// <summary>
        /// word Document Settings and gets cursor position 
        /// </summary>
        public static void WordSet()
        {
            object oMissing = System.Reflection.Missing.Value;
            Microsoft.Office.Interop.Word.Application WordApp;
            Microsoft.Office.Interop.Word.Document WordDoc;
            WordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
            #region  Document formatting 
            WordApp.ActiveDocument.PageSetup.LineNumbering.Active = 0;// Line number 
            WordApp.ActiveDocument.PageSetup.Orientation = Microsoft.Office.Interop.Word.WdOrientation.wdOrientPortrait;// Page orientation 
            WordApp.ActiveDocument.PageSetup.TopMargin = WordApp.CentimetersToPoints( float.Parse( "2.54" ) );// On the margins 
            WordApp.ActiveDocument.PageSetup.BottomMargin = WordApp.CentimetersToPoints( float.Parse( "2.54" ) );// On the next page margins 
            WordApp.ActiveDocument.PageSetup.LeftMargin = WordApp.CentimetersToPoints( float.Parse( "3.17" ) );// The left margins 
            WordApp.ActiveDocument.PageSetup.RightMargin = WordApp.CentimetersToPoints( float.Parse( "3.17" ) );// Right margins 
            WordApp.ActiveDocument.PageSetup.Gutter = WordApp.CentimetersToPoints( float.Parse( "0" ) );// Binding line position 
            WordApp.ActiveDocument.PageSetup.HeaderDistance = WordApp.CentimetersToPoints( float.Parse( "1.5" ) );// The header 
            WordApp.ActiveDocument.PageSetup.FooterDistance = WordApp.CentimetersToPoints( float.Parse( "1.75" ) );// The footer 
            WordApp.ActiveDocument.PageSetup.PageWidth = WordApp.CentimetersToPoints( float.Parse( "21" ) );// The paper width 
            WordApp.ActiveDocument.PageSetup.PageHeight = WordApp.CentimetersToPoints( float.Parse( "29.7" ) );// The paper height 
            WordApp.ActiveDocument.PageSetup.FirstPageTray = Microsoft.Office.Interop.Word.WdPaperTray.wdPrinterDefaultBin;// Paper source 
            WordApp.ActiveDocument.PageSetup.OtherPagesTray = Microsoft.Office.Interop.Word.WdPaperTray.wdPrinterDefaultBin;// Paper source 
            WordApp.ActiveDocument.PageSetup.SectionStart = Microsoft.Office.Interop.Word.WdSectionStart.wdSectionNewPage;// Start of section: new page 
            WordApp.ActiveDocument.PageSetup.OddAndEvenPagesHeaderFooter = 0;// Header, footer - Odd and even pages are different 
            WordApp.ActiveDocument.PageSetup.DifferentFirstPageHeaderFooter = 0;// Header, footer - Different home page 
            WordApp.ActiveDocument.PageSetup.VerticalAlignment = Microsoft.Office.Interop.Word.WdVerticalAlignment.wdAlignVerticalTop;// Vertical page alignment 
            WordApp.ActiveDocument.PageSetup.SuppressEndnotes = 0;// Do not hide endnotes 
            WordApp.ActiveDocument.PageSetup.MirrorMargins = 0;// Do not set the inside and outside margins of the home page 
            WordApp.ActiveDocument.PageSetup.TwoPagesOnOne = false;// Non-duplex printing 
            WordApp.ActiveDocument.PageSetup.BookFoldPrinting = false;// Manual double-sided front printing is not set 
            WordApp.ActiveDocument.PageSetup.BookFoldRevPrinting = false;// Manual double-sided back printing is not set 
            WordApp.ActiveDocument.PageSetup.BookFoldPrintingSheets = 1;// Print the default number of copies 
            WordApp.ActiveDocument.PageSetup.GutterPos = Microsoft.Office.Interop.Word.WdGutterStyle.wdGutterPosLeft;// The binding line is on the left 
            WordApp.ActiveDocument.PageSetup.LinesPage = 40;// Default page line count 
            WordApp.ActiveDocument.PageSetup.LayoutMode = Microsoft.Office.Interop.Word.WdLayoutMode.wdLayoutModeLineGrid;// The layout mode is "specify row grid only" 
            #endregion
            #region  Paragraph formatting 
            WordApp.Selection.ParagraphFormat.LeftIndent = WordApp.CentimetersToPoints( float.Parse( "0" ) );// The indentation left 
            WordApp.Selection.ParagraphFormat.RightIndent = WordApp.CentimetersToPoints( float.Parse( "0" ) );// Right indent 
            WordApp.Selection.ParagraphFormat.SpaceBefore = float.Parse( "0" );// Before paragraph spacing 
            WordApp.Selection.ParagraphFormat.SpaceBeforeAuto = 0;//
            WordApp.Selection.ParagraphFormat.SpaceAfter = float.Parse( "0" );// After the period of spacing 
            WordApp.Selection.ParagraphFormat.SpaceAfterAuto = 0;//
            WordApp.Selection.ParagraphFormat.LineSpacingRule = Microsoft.Office.Interop.Word.WdLineSpacing.wdLineSpaceSingle;// single-spaced 
            WordApp.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphJustify;// The paragraph 2 The alignment 
            WordApp.Selection.ParagraphFormat.WidowControl = 0;// Make control 
            WordApp.Selection.ParagraphFormat.KeepWithNext = 0;// On the same page as the next paragraph 
            WordApp.Selection.ParagraphFormat.KeepTogether = 0;// No paging in segments 
            WordApp.Selection.ParagraphFormat.PageBreakBefore = 0;// Before paragraph the paging 
            WordApp.Selection.ParagraphFormat.NoLineNumber = 0;// Cancel the line Numbers 
            WordApp.Selection.ParagraphFormat.Hyphenation = 1;// Cancel the period of word 
            WordApp.Selection.ParagraphFormat.FirstLineIndent = WordApp.CentimetersToPoints( float.Parse( "0" ) );// The first line indentation 
            WordApp.Selection.ParagraphFormat.OutlineLevel = Microsoft.Office.Interop.Word.WdOutlineLevel.wdOutlineLevelBodyText;
            WordApp.Selection.ParagraphFormat.CharacterUnitLeftIndent = float.Parse( "0" );
            WordApp.Selection.ParagraphFormat.CharacterUnitRightIndent = float.Parse( "0" );
            WordApp.Selection.ParagraphFormat.CharacterUnitFirstLineIndent = float.Parse( "0" );
            WordApp.Selection.ParagraphFormat.LineUnitBefore = float.Parse( "0" );
            WordApp.Selection.ParagraphFormat.LineUnitAfter = float.Parse( "0" );
            WordApp.Selection.ParagraphFormat.AutoAdjustRightIndent = 1;
            WordApp.Selection.ParagraphFormat.DisableLineHeightGrid = 0;
            WordApp.Selection.ParagraphFormat.FarEastLineBreakControl = 1;
            WordApp.Selection.ParagraphFormat.WordWrap = 1;
            WordApp.Selection.ParagraphFormat.HangingPunctuation = 1;
            WordApp.Selection.ParagraphFormat.HalfWidthPunctuationOnTopOfLine = 0;
            WordApp.Selection.ParagraphFormat.AddSpaceBetweenFarEastAndAlpha = 1;
            WordApp.Selection.ParagraphFormat.AddSpaceBetweenFarEastAndDigit = 1;
            WordApp.Selection.ParagraphFormat.BaseLineAlignment = Microsoft.Office.Interop.Word.WdBaselineAlignment.wdBaselineAlignAuto;
            #endregion
            #region  Font formatting 
            WordApp.Selection.Font.NameFarEast = " HuaWenZhong song ";
            WordApp.Selection.Font.NameAscii = "Times New Roman";
            WordApp.Selection.Font.NameOther = "Times New Roman";
            WordApp.Selection.Font.Name = " Song typeface ";
            WordApp.Selection.Font.Size = float.Parse( "14" );
            WordApp.Selection.Font.Bold = 0;
            WordApp.Selection.Font.Italic = 0;
            WordApp.Selection.Font.Underline = Microsoft.Office.Interop.Word.WdUnderline.wdUnderlineNone;
            WordApp.Selection.Font.UnderlineColor = Microsoft.Office.Interop.Word.WdColor.wdColorAutomatic;
            WordApp.Selection.Font.StrikeThrough = 0;// Delete the line 
            WordApp.Selection.Font.DoubleStrikeThrough = 0;// Double delete line 
            WordApp.Selection.Font.Outline = 0;// hollow 
            WordApp.Selection.Font.Emboss = 0;// Yang wen 
            WordApp.Selection.Font.Shadow = 0;// shadow 
            WordApp.Selection.Font.Hidden = 0;// The hidden text 
            WordApp.Selection.Font.SmallCaps = 0;// Small capital letter 
            WordApp.Selection.Font.AllCaps = 0;// All caps 
            WordApp.Selection.Font.Color = Microsoft.Office.Interop.Word.WdColor.wdColorAutomatic;
            WordApp.Selection.Font.Engrave = 0;// The spiral 
            WordApp.Selection.Font.Superscript = 0;// superscript 
            WordApp.Selection.Font.Subscript = 0;// The subscript 
            WordApp.Selection.Font.Spacing = float.Parse( "0" );// Between characters 
            WordApp.Selection.Font.Scaling = 100;// Characters zooming 
            WordApp.Selection.Font.Position = 0;// location 
            WordApp.Selection.Font.Kerning = float.Parse( "1" );// Font spacing adjustment 
            WordApp.Selection.Font.Animation = Microsoft.Office.Interop.Word.WdAnimation.wdAnimationNone;// Text effects 
            WordApp.Selection.Font.DisableCharacterSpaceGrid = false;
            WordApp.Selection.Font.EmphasisMark = Microsoft.Office.Interop.Word.WdEmphasisMark.wdEmphasisMarkNone;
            #endregion
            #region  Get cursor position 
            /**/////get_Information
            WordApp.Selection.get_Information( WdInformation.wdActiveEndPageNumber );
            // About the line number - Page number - Column number - location 
            //information  attribute 
            // Returns information about a specified selected content or area. variant  Type, read only. 
            //expression.information(type)
            //expression  A necessity. This expression returns 1 a  range  or  selection  Object. 
            //type long  Type, required. The information that needs to be returned. Recommend the following  wdinformation  Constants of 1 : 
            //wdactiveendadjustedpagenumber  Returns the page number that contains the active end of the specified selected content or area. If you set it 1 , and manually adjusted the page number, the adjusted page number is returned. 
            //wdactiveendpagenumber  Returns a page number containing the active end of the specified selected content or area on the page, calculated from the beginning of the document without regard to any manual adjustments to the page number. 
            //wdactiveendsectionnumber  Returns the section number that contains the active end of the specified selected content or area. 
            //wdatendofrowmarker  This parameter is returned if the selected content or area specified is located at the end of the row in the table  true . 
            //wdcapslock  This parameter is returned if the caps lock mode is valid  true . 
            //wdendofrangecolumnnumber  Returns the table column number that contains the active end of the specified selected content or area. 
            //wdendofrangerownumber  Returns the table row number that contains the end of the activity for the specified selected content or area. 
            //wdfirstcharactercolumnnumber  Returns the value of a specified selected content or area 1 The position of the characters. If the selected content or area is folded, the character number immediately following to the right of the selected content or area is returned. 
            //wdfirstcharacterlinenumber  Returns the first in the selection 1 A line number of characters. if  pagination  Properties for  false Or,  draft  Properties for  true , the return  - 1 . 
            //wdframeisselected  If the selected content or area is 1 Text box, this parameter is returned  true . 
            //wdheaderfootertype  return 1 , which indicates the type of header or footer that contains the specified selected content or area, as shown in the following table.   value   The type of header or footer 
            //- 1  There is no 
            //0  Even page headers 
            //1  Odd page header 
            //2  Even footer 
            //3  Odd footer 
            //4  The first 1 A header 
            //5  The first 1 A footer 
            //wdhorizontalpositionrelativetopage  Returns the horizontal location of the specified selected content or area. This location is the distance in pounds between the left side of the selected content or area and the left side of the page. Returns if the selected content or area is not visible  - 1 . 
            //wdhorizontalpositionrelativetotextboundary  Returns the horizontal position, in pounds, of the specified selected content or area to the left of the nearest surrounding body boundary. This parameter is returned if the selected content or area is not displayed on the current screen  - 1 . 
            //wdinclipboard  For more information on this constant, see  microsoft office 98 macintosh  Version of the language reference help. 
            //wdincommentpane  Returns if the selected content or area specified is in the annotation pane  true . 
            //wdinendnote  This parameter is returned if the selected content or area specified is in the endnote area of the page view, or in the endnote pane of a normal view  true . 
            //wdinfootnote  This parameter is returned if the selected content or area specified is located in the footnote area of the page view, or in the footnote pane of the normal view  true . 
            //wdinfootnoteendnotepane  This parameter is returned if the selected content or area specified is in the footnote or endnote area of the page view, or in the footnote or endnote pane of the normal view  true . For more information, see the previous section  wdinfootnote  and  wdinendnote  The instructions. 
            //wdinheaderfooter  This parameter is returned if the selected content or area specified is located in the header or footer pane, or in the header or footer of the page view  true . 
            //wdinmasterdocument  This parameter is returned if the selected content or area specified is located in the master document  true . 
            //wdinwordmail  return 1 The value indicates the location of the selected content or area, as shown in the following table. value   location 
            //0  The selected content or area is not present 1 In an email message. 
            //1  The selected content or area is in the email being sent. 
            //2  The selected content or area is in the email you are reading. 
            //wdmaximumnumberofcolumns  Returns the maximum number of table columns for any row in the selected content or area. 
            //wdmaximumnumberofrows  Returns the maximum number of rows in a table in the specified selected content or area. 
            //wdnumberofpagesindocument  Returns the number of pages of the document associated with the selected content or area. 
            //wdnumlock  if  num lock  Valid, this parameter is returned  true . 
            //wdovertype  If the overwrite mode is valid, this parameter is returned  true . available  overtype  Property changes the state of the rewrite mode. 
            //wdreferenceoftype  return 1 Is a value indicating the position of the selected content relative to a footnote, endnote, or annotation reference, as shown in the following table.   value   describe 
            // -  1  The selected content or area includes, but is not limited to, a footnote, endnote, or annotation reference. 
            //0  The selected content or area does not precede a footnote, endnote, or annotation reference. 
            //1  The selected content or area precedes the footnote reference. 
            //2  The selected content or area precedes the endnote reference. 
            //3  The selected content or area precedes the annotation reference. 
            //wdrevisionmarking  If the revision function is active, this parameter is returned  true . 
            //wdselectionmode  return 1 , which indicates the currently selected schema, as shown in the following table.   value   The selected mode 
            //0  Conventional selected 
            //1  Extend the selected 
            //2  Selected columns 
            //wdstartofrangecolumnnumber  Returns the column number of the table in which the starting point of the selected content or area is located. 
            //wdstartofrangerownumber  Returns the row number of the table in which the starting point of the selected content or area is located. 
            //wdverticalpositionrelat
                

Important Correction

In the two versions of this article before November 24, 2014, I’d stated that virtual destructors weren’t necessary in what was the HumanInteractions8/HumanInteractions9 example. That was incorrect, and I hope earlier readers are somehow made aware of my mistake so they don’t make it themselves. I’m very sorry for the mis-statement.

Introduction

Throughout the years I’ve seen many people say teaching Object Oriented Programming (OOP) fundamentals with C++ isn’t recommended because of the language’s complexity. Java seems to be the standard, and while I have no gripe with the choice, I still find myself rolling my eyes every time I hear the first assertion.

C++ tutorials seem to be a dime a dozen, and other languages are more talked about these days, but I feel the urge to write a small-ish C++ OOP tutorial for a beginner, that gets to the heart of object orientation. I won’t go into much of the complexities, because an introduction should not be something that focuses on items which aren’t necessary. Tutorials of this nature aren’t common, as far as I’ve seen, so let us begin.

If you are a beginner, skip to the next section now. The following paragraphs are for more advanced programmers to understand my approach.

In many ways, this is a response to articles like Akhil Mittal’s, and several other OOP introductions I’ve read, as well as the claim against C++. As such, I’ve endeavored to keep jargon to an absolute minimum, and focus on things a beginner will need to know to start understanding the bigger C++ programming picture. I believe there is one programming book that takes an approach similar to the following, but I have forgotten the title. Everything else I’ve come across has not been beginner friendly in my opinion, and even though the following might also have a few rough spots, I’ve tried to make it something a new programmer can turn to for a relatively quick grasp of the necessary concepts.

Like many, my programming interest began long ago. Back then learning was often a matter of copying code from a magazine, and then running it and fixing all the typos introduced because of the tediousness of the manual typing. Surprisingly, even though the magazines were semi-professional, their code often contained bugs. Because of that, and other issues, many of those examples were initially over my head, but the iterative process of beating my noggin into a wall eventually brought insight. I believe that is the nature of true learning, and I hope the following pays tribute to that heritage without introducing the bugs that prolonged my own learning process (but also made it deeper).

Preliminaries

A programmer needs two things: a computer and a compiler. If your computer’s Operating System (OS) is Windows and you are being cheap, I recommend Microsoft’s Visual Studio Community Edition (VSCE). For the price of nothing Microsoft has made an absolutely fantastic tool available for our use. If you use another OS, I can’t give any recommendations due to my own unfamiliarity with those platforms.

Once you have your compiler set up by using the standard installation procedure, the next step is to create a project in it. To do this in VSCE go to ‘File -> New Project,’ and select a ‘Visual C++ -> General -> Empty Project.’ Place it wherever you want on your system, although I recommend creating a forward-thinking subdirectory structure at this point. Of course, without experience you won’t know what a forward-thinking approach is.

My recommendation is to place the projects for this tutorial into a subdirectory called «[User]ProgramsMyProgsInitialLearning.» For the following, one project will suffice, but you can make each step its own project if you wish, with each of them being a subdirectory off of the InitialLearning directory.

On my system the «Programs» subdirectory is only populated with subdirectories, and includes «Backups,» «Libraries,» «MyProgs,» «OthersProgs,» «Misc,» and «TheoryAndExamples.» The ultimate reason behind this layout is something you won’t need for our work, but will need in the future. Complex programs almost always require external libraries, and this subdirectory arrangement results in an easier way to find those libs than if they are scattered all over your hard drive. Ultimately, that is fewer mouse clicks in Visual Studio.

The purpose of coding is to solve problems, even if that is only to keep the user entertained for a while. OOP is a method of mirroring the problems in code as directly as possible. The best way to understand this statement is with an example, so let us model one: a human interaction.

For our fictional case we will represent two people talking to each other. All we want to happen is for one person to say «Good morning, Jennie!,» and the other to respond, «Hello Joe!» So for the name of this project use «HumanInteraction.» When creating a new project in Visual Studio, if you are in the ‘InitialLearning’ subdirectory mentioned earlier and you create a project named ‘HumanInteraction’, Visual Studio will create it in a subdirectory named ‘HumanInteraction,’ so you don’t need to manually create the location.

In C++ we use the word class to represent a desired type of object. We are modeling humans, so the C++ equivalent is class Human. A routine, sometimes called ‘function,’ is the method classes use to accomplish tasks. In our case we want one to ‘talk’ to another, so ‘talk’ is a good descriptive name for our first function.

Objects have attributes, just like the real world. For instance, the attributes of the previous scenario are the people’s names: ‘Jennie’ and ‘Joe.’

Let us begin expressing a ‘Human’ object in C++, with a ‘name’ attribute. The following code includes things I haven’t introduced yet, but you may be able to understand the fundamental concept of what is going on given the words used. They will be explained afterwards.

class Human {
   private:
      std::string nameC;

   public:
      Human(const std::string & name) : nameC(name) { }
   };

The first new thing you will notice when reading from top to bottom is the opening brace ({). Braces are the main way to delineate objects and ‘scopes’ to the compiler. In this case everything between the opening brace and closing brace (the one with the «;» after it) is the definition of the ‘Human’ class.

By ‘scope’ in the previous paragraph, I mean that the items declared within the braces will be destroyed at the ending brace unless you take actions to keep that from happening. There might be more on this later, if this writing doesn’t become too long.

The next item in the Human declaration is the private:. This means that items in that section are only available to the class itself. The person’s name has been declared in this section, and a logical first thought upon hearing this is that your name is not ‘private’ to you — all your friends know it. That is true, but they have had interactions that made your name known to them. Most random strangers will have no idea about your identity unless you write it on a sticker and paste it on yourself.

It is a good idea to make as many class items as possible private. This keeps other objects from modifying them recklessly. If you made the ‘name’ public any other object could change it at their whim — something you most definitely don’t want!

That ‘name’ is declared as a std::string. C++ has a standard library to make your life easier, and items in that library are ‘contained’ in what is called the std namespace. I will not go into namespaces here, because it takes us too far from our current topic, and gets us into those ‘complexities.’ But I will mention that there is a method which enables you to eliminate the std:: in front of string, and reduce typing. All that is needed is to add a line before the class:

using namespace std;

When you start dealing with header files (which I don’t cover here), be aware that it is not a good idea to ‘use’ namespaces in them like this. You should explicitly specify everything in headers (i.e., «std::vector«), but using namespaces in .cpp files is only problematic if they are #included in other units as header files, which I, and almost everyone else I’ve seen, strongly discourage.

(Some people make an exception for the standard library, and do include using namespace std; in header files, but I recommend having much more experience before you do so. I don’t, because I think it’s a bad habit.)

I should also explain the C at the end of nameC.

Large programs often become difficult to figure out, and it is helpful to be able to tell variables that are a permanent part of the class (such as ‘name’) from others that are only used within single functions. My method of delineating these is to use the C at the end of the variable name in order to indicate it is part of the ‘Class.’ You will often come across code that uses a prepended m_ to do the same thing, where m_ stands for ‘member.’ A ‘C’ is fewer keystrokes than ‘m_’, and fewer strokes are better when you can get by with them, in my opinion.

Of course, this string is an object we can place the person’s name into. In our case, one of the names will be «Joe,» and the other will be «Jennie.» Strings are just characters placed back to back in a computer’s memory.

The next line is public:. As you might suspect from our private conversation, items placed in this section can be accessed by other objects.

The Human in the following line is a very important item. It is known as a ‘constructor,’ and is the method that must be called in order to create a Human in the computer’s memory. More could be said about constructors at this point, such as they can be made private if you want to make construction possible in a very specific way that usually isn’t needed. And they can be overloaded, which we will discuss later.

In our case I’ve placed a const std::string & name in parenthesis after Human. This is an item the caller of the constructor must supply, and it is defined here in order to force the caller to send it. The const qualifier indicates that the std::string won’t be modified by the routine. That qualification often allows the compiler to optimize the code for better speed and efficiency.

In C++, the item in the parenthesis of our our constructor is called an ‘argument.’ It isn’t really ‘arguing’ about anything; the word was probably chosen because it meant something like ‘talking point.’ It is something passed between the ‘talker’ and the ‘talkee.’

Interestingly, I’m unaware of a better word for this concept, even though ‘argument’ doesn’t express the intended meaning very well. The phrase «communication point,» which could be abbreviated «compoint» could be better, but ‘argument’ is accepted, and the word you will need to know. (Merriam-Webster’s sixth definition probably originated after programming languages adopted the word.)

Following the closing parenthesis there is a colon, :. Constructors needed a way of initializing class variables before running any code within the constructor body, in order to be more efficient, and everything between the «:» and the following brace ({) are C++’s way of doing that. They are called ‘initialization lists.’ In this one the nameC class variable is set to whatever the calling object sets the name argument to.

Then, following the initialization list, the body of the constructor is defined. In this case the constructor doesn’t need to do anything, so it is empty. Thereby the { }.

Finally, the class definition is closed with the «};«. You can also say that is the end of its scope, to use an earlier word.

Before filling in the talk function let me introduce a routine required by every program in one way or another: the main function. C++’s standards require every program to have one.

The main function begins initiating — and finishes terminating — a majority of the objects and logic used in the program. It is the routine that will create and destroy our Humans. You can consider it to be the ‘God’ function if you want.

I said main initiates and terminates a majority of the objects. The exception to this are global items, which I also won’t go into here.

With all of these preliminaries out of the way, the entire program follows. To use it within Visual Studio, right click on the ‘Source Files’ filter in the right hand pane (unless you’ve modified the default screen layout) and select ‘Add -> New Item.’ Then select the ‘C++ file (.cpp)’ option. You can leave it named as ‘Source,’ or rename it ‘main’ or another name if you wish. Once you press the ‘Add’ button a new file appears in the editor window. Copy and paste the following into it:





#include <string>
#include <iostream>

class Human {
   private:
      std::string nameC;

   public:
      Human(const std::string & name) : nameC(name) { }

      std::string name() const { return nameC; }
      
      void talkTo(const Human & person) const {
         std::cout << nameC << " says: Hello, " << person.name() << "!" << std::endl;
         }
   };

int main() {
   Human joe("Joe");
   Human jennie("Jennie");
   joe.talkTo(jennie);
   jennie.talkTo(joe);
   std::cout << std::endl << "Press 'Enter' to exit";
   std::cin.ignore();
   return 0;
   }

Download HumanInteractions1.zip — 9KB

If you press the ‘Local Windows Debugger’ button in Visual Studio, you should see the following:

Image 1

Congratulations! You have just executed your first object oriented program. (Barring copy/paste errors, or other difficulties that should be fixable by going through the directions again.)

I should mention that the const in the std::string name() const { return nameC; } line tells the compiler that the function will not change the state of the object in any way. In this case we are simply returning a copy of the nameC variable, and returning copies doesn’t modify the original. Similar to the previously mentioned const, this allows the compiler to optimize for additional speed in some cases. (The same holds true for the second const after talkTo.)

I should also briefly introduce cout. It is simply the console output, which is the window in the screenshot. In the code, the << can be thought of as sending the items following it to the console. For instance, std::cout << std::endl << "Press 'Enter' to exit"; sends an endline (like a ‘Return’ on an old fashioned typewriter, or ‘Enter’ in a word processor), followed by the phrase «Press ‘Enter’ to exit.» The << after std::endl allows the following string to be strung together with the std::endl.

If you want to reduce typing, the following is the program with the using namespace std; included:

#include <string>
#include <iostream>

using namespace std;

class Human {
   private:
      string nameC;

   public:
      Human(const string & name) : nameC(name) { }

      string name() const { return nameC; }
      
      void talkTo(const Human & person) const {
         cout << nameC << " says: Hello, " << person.name() << "!" << endl;
         }
   };

int main() {
   Human joe("Joe");
   Human jennie("Jennie");
   joe.talkTo(jennie);
   jennie.talkTo(joe);
   cout << endl << "Press 'Enter' to exit";
   cin.ignore();
   return 0;
   }

From the preceding discussion you might already have an idea of what is occurring in this program, but let me touch upon a few items.

First, as mentioned previously, everything is initiated in main. A Human named «Joe» is created, then «Jennie» is created. Joe ‘talks’ to Jennie, and she responds.

And note that I changed the function name to talkTo instead of talk as I said earlier. The reason is because I realized talkTo is a more descriptive, richer name than talk in this case. Better descriptions in the code itself make it easier to debug. The process of changing things this way is called ‘refactoring.’

After Jennie and Joe ‘talk,’ the program waits for you to press ‘Enter’ so it can terminate.

One question you may have is why «Joe» is also referred to as joe in the code, without capitalization. The answer is that the «Joe» (in quotes) is the ‘attribute’ of the computer object joe. That attribute could be changed to anything, like «Mary», but the computer would still access it through the variable joe.

Another valid question is why didn’t I name the object Joe instead of joe? Habit and consistency, in order to make things simple for reading are the reasons.

I, and most other programmers, like to distinguish Object declarations from variables. An easy way to do so is to use Capitals for Object declarations, and camelCase for the instantiation of those declarations in variables. You will come across other methods of approaching this problem in your future, but the method I am presenting is used in many places.

There are also many other ways of indenting code. For example, one of the most used looks like this:

#include <string>
#include <iostream>

using namespace std;

class Human
{
private:
   string nameC;

public:
   Human(const string & name) : nameC(name) { }

   string name() const { return nameC; }
   
   void talkTo(const Human & person) const
   {
      cout << nameC << " says: Hello, " << person.name() << "!" << endl;
   }
};

int main()
{
   Human joe("Joe");
   Human jennie("Jennie");
   joe.talkTo(jennie);
   jennie.talkTo(joe);
   cout << endl << "Press 'Enter' to exit";
   cin.ignore();
   return 0;
}

I have my own logical reasons for using the earlier style — namely the indention level automatically delineates everything associated with an indention ‘block.’ I consider the closing brace to be part of the block, which makes finding the next indention level much simpler. But holy wars have raged over this issue, so when you see other styles, accept them and continue on.

Object Relationships

The preceding program introduced the heart of programming C++ in an object oriented manner. But there is one more topic I am compelled to add, because without an understanding of it your programming knowledge will be limited for some time.

Objects are often related to other objects, just as items in real life are related to other items. Many times you need to create a list of objects that are somehow similar, but not all the same, and then take different actions based upon those differences.

As an example, let us deal with a list of people saying ‘Hi’ to other people. I will tread on stereotypes, and do so badly, so bear with me, and feel free to correct all the mistakes in the comments.

As you know, almost every culture has its own language, or local accent. In a non-object-oriented programming language, dealing with these differences is usually much more difficult than doing so in object orient languages. In fact, the object-oriented approach gives a huge advantage in ease of coding as well as run time performance in most cases.

Imagine you have a room full of people, and imagine they say ‘Hi’ to each other. Let us make this into an unlikely scenario, but something that is fairly easy to mentally picture. These people are arranged in a circle, and the first person says «Hi» to all the other people, one at a time, starting with the person on their left, who can be considered to be person number 2. After #1 says «Hi» to everyone, #2 then says «Hi» to #1, then #3, #4, etc, until he/she finishes, and #3 repeats the process, then the next person, until everyone has greeted everyone else.

Now, to throw the final twist into it, instead of «Hi,» the talker will use their own cultural word. I won’t go into the complete scenarios, because I don’t know them (for instance, in Japanese ‘David’ sounds more like ‘Dahvid’ if memory serves correctly).

To give an idea of how object orientation eases programming, I need to show the basics of how a non-OO approach tackles the problem. In that approach the program would have to iterate through the people and determine their nationality/culture while performing the talk routine. C++ is perfectly capable of handling non-OO programs, so the loop to do so would look something like the following. (I’ve kept some object orientation elements in, to make it easier to understand.)

for (int talkingPerson=0; talkingPerson<numberOfPeople; ++talkingPerson) {

      for (int talkedToPerson=0; talkedToPerson<numberOfPeople; ++talkedToPerson) {

      if (talkingPerson != talkedToPerson) { 
                  if (talkingPerson.culture() == "Japanese") cout << "Konnichiwa, " <<
                     talkedToPerson.name();
         else if (talkingPerson.culture() == "German") cout << "Hallo, " <<
                     talkedToPerson.name();
         else if (talkingPerson.culture() == "Hawaiian") cout << "Aloha, " <<
                     talkedToPerson.name();
                  }

      }
   }

As I said, I used elements of object orientation for ease of comprehension. It isn’t important that you understand everything the code is doing, but it is important to note that the inner portion of the code, consisting of the if statements (which I’ve bolded and italicized), quickly becomes very long as more cultures are involved. The computer will have to go through those checks every iteration, which takes a little time. That time is almost insignificant to us, because computers are incredibly fast today, but that time still passes, and can be reduced.

Object orientation greatly simplifies the code. The loop becomes:

for (int talkingPerson=0; talkingPerson<numberOfPeople; ++talkingPerson) {
   for (int talkedToPerson=0; talkedToPerson<numberOfPeople; ++talkedToPerson) {
      if (talkingPerson != talkedToPerson) {          talkingPerson->talkTo(talkedToPerson);
         }
      }
   }

That’s it. All of the cultural if processing is eliminated. And adding more cultures doesn’t affect this portion of the code. Also, the time that is taken for each loop is pretty much the same whether one culture or a thousand are involved.

Pointers/References

Before developing a compilable ‘talking’ program for our new scenario, and showing the details involved, there is one more item I need to touch upon: the difference between «.» and «->» in C++. These are two methods of referring to objects and variables.

Everything you create in a program resides in memory somewhere. For example, let’s take our earlier joe. It was an object created in main, and we accessed its functions with the «.» syntax. (I’m talking about the line, joe.talkTo(jennie);.)

As a vast understatement, let us say there are only 1,000 memory slots on the computer running that program. And the memory location where the joe object begins is at #703. When the program is compiled (remember pressing the ‘Local Windows Debugger’ button in Visual Studio?), the executable knows how to directly access #703 when it is given the term ‘joe‘. In those situations you simply use the «.» syntax.

But there is one more way to access joe if you wish, and that is through what is called a pointer. It is perfectly acceptable to put the beginning location of joe into another memory position, and use that secondary position to ‘point’ to joe. To say this another way, we can place «703» into that other location. In fact, it is often quite useful to do this. When joe is accessed that way, we use the «->» syntax.

To simplify at the cost of not always being correct, but to give a general mental picture, if we are dealing with the real location of something, we use «.«. If we are dealing with a pointer to the location, we use «->«. (A hard rule that is much more correct is «If we are dealing with a pointer and don’t dereference it, we always use the -> nomenclature to access the functions associated with the object.» But you don’t know what ‘dereferencing’ is, yet, so pretend you didn’t read that!)

The simple rule is simple, but it is easy to get confused due to the fluidity with which pointers can become non-pointers, and non-pointers (called references in some circumstances, objects, or variables in others) can become pointers. These are transformed by the ‘address of’ operator, «&«, and the ‘dereferencing’ operator, «*«.

The ‘address of’ operator, «&«, is used to determine the memory location of a variable or object. And, as you may be guessing, the ‘dereferencing’ operator, «*«, is used to treat the value held in a pointer as the direct location of the variable or object. (Now you don’t have to pretend any more.)

Unfortunately, both of these operators have secondary meanings in other contexts, to confuse the issue. (Or ‘fortunately,’ for the larger scope of C++, because they are valuable constructs, but they make your initial learning a little more difficult.) The ‘address of’ operator, «&«, can also be used to delineate a variable called a reference, and the ‘dereferencing’ operator, «*«, can be used to indicate a variable that is a pointer. With a little familiarity they are easy to tell apart, but it took me a while to become comfortable with them, so if you don’t immediately get it, revisit the topic a few more times. You are not alone.

(As a general rule, if these symbols are on the left side of an ‘=‘ sign they are declaring a pointer or reference variable. If they are on the right, they are dereferencing or taking the address of something.)

Let us redo the previous program to make Jennie and Joe talk to each other repetitiously, using these constructs.

#include <string>
#include <iostream>

using namespace std;

class Human {
   private:
      string nameC;

   public:
      Human(const string & name) : nameC(name) { }

      string name() const { return nameC; }
      
      void talkTo(const Human & person) const {
         cout << nameC << " says: Hello, " << person.name() << "!" << endl;
         }
   };

   
int main() {
   Human joe("Joe");
   Human jennie("Jennie");
   joe.talkTo(jennie);
   jennie.talkTo(joe);
   
      
                     Human * pointerToJoe = &joe;
   
      Human * pointerToJennie = &jennie;
   
      pointerToJoe->talkTo(jennie);
   pointerToJennie->talkTo(joe);
   
         pointerToJoe->talkTo(*pointerToJennie);
   pointerToJennie->talkTo(*pointerToJoe);
   
            Human & referenceToJoe = *pointerToJoe;
   Human & referenceToJennie = *pointerToJennie;
   
               
      referenceToJoe.talkTo(referenceToJennie);
   referenceToJennie.talkTo(referenceToJoe);   
   
   cout << endl << "Press 'Enter' to exit";
   cin.ignore();
   return 0;
   }

Download HumanInteractions2.zip — 9KB

As you can see by the output, all of these are equivalent, it is just the syntax that differs:

Image 2

Pointers and references are powerful, but demanding tools for your toolbelt. When used like the previous, they are safe, but as you get deeper into C++ there are many instances where pointers will bite you in the ankle with a venomous sting that will be remembered for some time. References also have some ‘gotcha’s associated with them, but they usually don’t bite quite so hard. (Here’s an article on pointers, and here’s an article on the reference issues, for continued learning once you are done with this.)

Virtual(ly Magic!)

The reason I brought up pointers is because in C++ they can be used in a very powerful way: to call virtual functions.

In order to understand virtual functions, let me step back and talk about another item: base classes and sub-classes.

Remember the set of if statements that were going to rapidly grow as the number of cultures involved increased in our ‘talking’ scenario? Those statements were handling different types of Humans, and an easy way to picture base classes and sub-classes is to think of a generic Human as a base class, whereas a ChinesePerson is a sub-class of Human. (AmericanPerson is also a sub-class, so no superiority is implied for anybody.)

Here is that relationship expressed in C++:

class Human {
 
   };

class ChinesePerson : public Human {

   };

There is no reason to stop there, although I will as far as code goes. We could derive NorthernChinesePerson from ChinesePerson, and further derive more specific types of northerners from that class if we so desired.

Given the previous code definition, the ChinesePerson has access to all the public items in Human, and it can also access anything defined as protected in the Human class.

To give more insight, let me put together a quick program.

Pretty much every human can ‘talk’, so I will modify the original program around that to clarify things. First, let us make a program in which the base class has a talkTo function as a public method:

#include <string>
#include <iostream>

using namespace std;


class Human {
   private:
      string nameC;

   public:
      Human(const string & name) : nameC(name) { }

      string name() const { return nameC; }
      
      void talkTo(const Human & person) const {
         cout << nameC << " says: Hello, " << person.name() << "!" << endl;
         }
   };


class ChinesePerson : public Human {
   public:
      ChinesePerson(const string & name) : Human(name) { }
   };


int main() {
   Human joe("Joe");
   ChinesePerson li("Li");
   
            
   li.talkTo(joe);

      joe.talkTo(li);
   
   cout << endl << "Press 'Enter' to exit";
   cin.ignore();

   return 0;
   }

Download HumanInteractions3.zip — 9KB

Upon running, you will see that this executes pretty much as before:

Image 3

Both joe and li are able to talk to each other using the talkTo function. But if talkTo is moved into the private section of Human, only joe will be able to use it. Change the Human definition to the following, and try rerunning the program:

class Human {
   private:
      string nameC;
      
      void talkTo(const Human & person) const {
         cout << nameC << " says: " << "Hello, " << person.name() << "!" << endl;
         }

   public:
      Human(const string & name) : nameC(name) { }

      string name() const { return nameC; }
   };

Now you get an error saying that Human::talkTo" is inaccessible for the li.talkTo(joe); line:

Image 4

That is because Humans, and only Humans can access items in private sections of their class. So let us make the talkTo function public again.

Now we start facing the interesting question we began with: how to get li to talk in his own language. Right now all he can do is say «Hello, [name]».

The first iteration to a solution is to give ChinesePeople their own talkTo function:

#include <string>
#include <iostream>

using namespace std;


class Human {
   protected:
      string nameC;

   public:
      Human(const string & name) : nameC(name) { }

      string name() const { return nameC; }

      void talkTo(const Human & person) const {
         cout << nameC << " says: Hello, " << person.name() << "!" << endl;
         }

   };


class ChinesePerson : public Human {
   public:
      ChinesePerson(const string & name) : Human(name) { }

      void talkTo(const Human & person) const {
         cout << nameC << " says: Néih hóu, " << person.name() << "!" << endl;
         }
   };


int main() {
   Human joe("Joe");
   ChinesePerson li("Li");

   li.talkTo(joe);

      joe.talkTo(li);
   
   cout << endl << "Press 'Enter' to exit";
   cin.ignore();

   return 0;
   }

Download HumanInteractions4.zip — 9KB

When you execute this program, notice the «Néih hóu»:

Image 5

Image 6

The objects did talk to each other, but something got pretty messed up in translation!

The problem boils down to character sets, and how different languages are represented with ‘ones’ and ‘zeros’ in a computer’s memory. I won’t touch upon this subject, except to give a solution (without much explanation) to solve the issue.

Google, Bing, DuckDuckGo, and the other search engines are definitely one of a programmer’s most used tools. A search for «visual studio console wstring» bring up this StackOverflow page, and it gives one method to circumvent the problem.

Experience told me that part of the issue was due to using std::string instead of std::wstring, which is why I chose that search term. To fix the issue, the program needs to be rewritten as follows:

#include <string>
#include <iostream>
#include <io.h>
#include <fcntl.h>

using namespace std;


class Human {
   protected:
      wstring nameC;

   public:
      Human(const wstring & name) : nameC(name) { }

      wstring name() const { return nameC; }

      void talkTo(const Human & person) const {
         wcout << nameC << " says: Hello, " << person.name() << "!" << endl;
         }

   };


class ChinesePerson : public Human {
   public:
      ChinesePerson(const wstring & name) : Human(name) { }

      void talkTo(const Human & person) const {
         wcout << nameC << " says: Néih hóu, " << person.name() << "!" << endl;
         }
   };


int main() {
   _setmode(_fileno(stdout), _O_U16TEXT);
   Human joe(L"Joe");      ChinesePerson li(L"Li");

   li.talkTo(joe);

      joe.talkTo(li);
   
   wcout << endl << "Press 'Enter' to exit";
   cin.ignore();

   return 0;
   }

Download HumanInteractions5.zip — 9KB

When executed, the expected result is obtained:

Image 7

Unfortunately we cannot use true Chinese characters without a lot more effort (as far as I know), so I will leave it at this textual state.

(Actually, looking at it a little more, possibly not so much is required. It seems all you would have to do is hack the registry so that consoles could use a font like Arial Unicode MS. If you ever want to play with that some more, I believe these are the characters for this instance: 你好. Now let’s get back to work!)

Finally! The Introductions!

At last we have the background material to begin solving our ‘talking’ problem. Since I have not yet shown a virtual example, let me first extend the previous to illustrate how the problem could be solved without it. We will fill in that long if loop, and make some more modifications. Note that I have removed the talkTo routine from the Human class, in order to emphasize that each type of culture is doing its own ‘talking.’ I have also showed what it takes to iterate through a list, and talk that way:

#include <string>
#include <iostream>
#include <io.h>
#include <fcntl.h>
#include <vector>

using namespace std;



enum class Culture {
   Chinese = 1,      American,                           Unknown                                                                                                     };


class Human {
   protected:
      wstring nameC;
            Culture cultureC;

   public:
            Human(const wstring & name, Culture culture) : nameC(name), cultureC(culture) { }
      
                                                                                                
      wstring name() const { return nameC; }

            Culture culture() const { return cultureC; }
   };


class AmericanPerson : public Human {
   public:
            AmericanPerson(const wstring & name) : Human(name, Culture::American) { }

      void talkTo(const Human & person) const {
         wcout << nameC << " says: Hello, " << person.name() << "!" << endl;
         }
   };


class ChinesePerson : public Human {
   public:
            ChinesePerson(const wstring & name) : Human(name, Culture::Chinese) { }

      void talkTo(const Human & person) const {
         wcout << nameC << L" says: Néih hóu, " << person.name() << L"!" << endl;
         }
   };


int main() {
   _setmode(_fileno(stdout), _O_U16TEXT);
   AmericanPerson joe(L"Joe");
   ChinesePerson li(L"Li");

         li.talkTo(joe);
   joe.talkTo(li);

         
   wcout << endl << "Now talking by iterating over the list:" << endl << endl;

         vector<Human*> people;

      people.push_back(&li);
   people.push_back(&joe);

            
   for (int speaker=0, numPeople=people.size(); speaker<numPeople; ++speaker) {

      for (int listener=0; listener<numPeople; ++listener) {

         if (listener != speaker) {       
            Culture culture = people[speaker]->culture();
            
            if (culture == Culture::American) {
                                             
               AmericanPerson * ap = static_cast<AmericanPerson*>(people[speaker]);
               ap->talkTo(*people[listener]);
               }
            
            else if (culture == Culture::Chinese) {
               ChinesePerson * cp = static_cast<ChinesePerson*>(people[speaker]);
               cp->talkTo(*people[listener]);
               }

            else {
               wcout << "Culture unknown - programming error" << endl;
               }
            }
         }
      }

   
   wcout << endl << "Press 'Enter' to exit";
   cin.ignore();

   return 0;
   }

Download HumanInteractions6.zip — 9KB

The program is not so small anymore, but it shows the complexity of coding without virtual functions, and does what is desired:

Image 8

The issue we now have is we wish to iterate through a list of Humans, and have each one ‘talk’ in their turn, but the ‘talking’ function is dependent upon the type of Human doing the talking. What we really want is a generic talkTo routine that the sub-classes can implement however they wish, and that the computer can call automatically based on type.

This is where virtual functions come in. Public routines (or protected routines, for that matter) marked virtual can be overridden by the sub-classes, and when they are called through a pointer to the base class in which the function is declared, the program will figure out the correct function to call behind the scenes. I will add a few more types of Humans, and solve the initial problem, and do so without the Culture enum of the previous approach:

#include <string>
#include <iostream>
#include <vector>
#include <io.h>
#include <fcntl.h>

using namespace std;


class Human {
   protected:
      wstring nameC;

   public:
      Human(const wstring & name) : nameC(name) { }

      wstring name() const { return nameC; }

      virtual void talkTo(const Human & person) const { }
                        
            
               };


class AmericanPerson : public Human {
   public:
      AmericanPerson(const wstring & name) : Human(name) { }

                              
      void talkTo(const Human & person) const override {
         wcout << nameC << " says: Hello, " << person.name() << "!" << endl;
         }
   };


class ChinesePerson : public Human {
   public:
      ChinesePerson(const wstring & name) : Human(name) { }

      void talkTo(const Human & person) const override {
         wcout << nameC << L" says: Néih hóu, " << person.name() << L"!" << endl;
         }
   };


class MexicanPerson : public Human {
   public:
      MexicanPerson(const wstring & name) : Human(name) { }

      void talkTo(const Human & person) const override {
         wcout << nameC << L" says: ¡Hola!, " << person.name() << L"!" << endl;
         }
   };


class GhettoSlanger : public Human {
   public:
      GhettoSlanger(const wstring & name) : Human(name) { }

      void talkTo(const Human & person) const override {
         wcout << nameC << L" says: Yo, Homey! Whassup?" << endl;
         }
   };


class JapanesePerson : public Human {
   public:
      JapanesePerson(const wstring & name) : Human(name) { }

      void talkTo(const Human & person) const override {
         wcout << nameC << L" says: Konnichiwa, " << person.name() << L"!" << endl;
         }
   };


int main() {
   _setmode(_fileno(stdout), _O_U16TEXT);

   AmericanPerson joe(L"Joe");
   ChinesePerson li(L"Li");
   MexicanPerson jose(L"Jose");
   GhettoSlanger mark(L"Mark");
   JapanesePerson hana(L"Hana");

   vector<Human*> people;
   people.push_back(&joe);
   people.push_back(&li);
   people.push_back(&jose);
   people.push_back(&mark);
   people.push_back(&hana);

   for (int speaker=0, numPeople=people.size(); speaker<numPeople; ++speaker) {
      for (int listener=0; listener<numPeople; ++listener) {
         if (speaker != listener) {
            people[speaker]->talkTo(*people[listener]);
            }
         }
      wcout << endl;
      }
   
   wcout << "Press 'Enter' to exit";
   cin.ignore();

   return 0;
   }

Download HumanInteractions7.zip — 9KB

Image 9

And with that, the solution is complete. You have seen how to create objects in C++, and how virtual functions allow you to eliminate logic checks in many circumstances. What I have just showed you is at the heart of C++ Object Orientation, and is very useful in many circumstances. I hope this helps you achieve a modicum of mastery much faster than I was able to.

Before wrapping this up, I will mention that you will often see items being created through new. Doing so would have eliminated some of the code in the previous main function. new creates an object somewhere in the computer’s ‘heap’ memory, to give you another term for further study. It then returns the address to that position (in the form of a pointer) to you.

Knowing that, a first iteration would be the following, but it is incredibly naive, and you should NEVER DO IT! (Sorry for shouting, but it’s kind of important.)

int main() {
   _setmode(_fileno(stdout), _O_U16TEXT);

   vector<Human*> people;
   people.push_back(new AmericanPerson(L"Joe"));                                                         people.push_back(new ChinesePerson (L"Li"));
   people.push_back(new MexicanPerson (L"Jose"));
   people.push_back(new GhettoSlanger (L"Mark"));
   people.push_back(new JapanesePerson (L"Hana"));

   for (int speaker=0, numPeople=people.size(); speaker<numPeople; ++speaker) {
      for (int listener=0; listener<numPeople; ++listener) {
         if (speaker != listener) {
            people[speaker]->talkTo(*people[listener]);
            }
         }
      wcout << endl;
      }
   
   wcout << "Press 'Enter' to exit";
   cin.ignore();

   return 0;
   }

The solution eliminates the need to address each person with a variable name, and the solution is shorter than the previous code, but the problem is that none of the objects will be deleted at the end of the scope this way. The earlier solutions always ended up calling what is called the destructor of the objects, but this one doesn’t.

One solution for that is to modify the program to this:

class Human {
   protected:
      wstring nameC;

   public:
      Human(const wstring & name) : nameC(name) { }

            virtual ~Human() { }
      
                  
      wstring name() const { return nameC; }

      virtual void talkTo(const Human & person) const { }
   };



int main() {
   _setmode(_fileno(stdout), _O_U16TEXT);

   vector<Human*> people;
   people.push_back(new AmericanPerson(L"Joe"));
   people.push_back(new ChinesePerson (L"Li"));
   people.push_back(new MexicanPerson (L"Jose"));
   people.push_back(new GhettoSlanger (L"Mark"));
   people.push_back(new JapanesePerson (L"Hana"));

   for (int speaker=0, numPeople=people.size(); speaker<numPeople; ++speaker) {
      for (int listener=0; listener<numPeople; ++listener) {
         if (speaker != listener) {
            people[speaker]->talkTo(*people[listener]);
            
                                                                                                }
         }
      wcout << endl;
      }
   
   wcout << "Press 'Enter' to exit";
   cin.ignore();

   while (!people.empty()) {
      delete people.back();
      people.pop_back();
      }

   return 0;
   }

Download HumanInteractions8.zip — 9KB

Now, at the end, the objects will be deleted. But even this solution is not the best, because if bad things happen between the «people.push_back(new JapanesePerson (L"Hana"));» line and the «while (!people.empty()) {» line, the «while (!people.empty()) {» line would never be reached, and the objects would be ‘leaked,’ as before.

The current best paradigm for solving this problem is to use some helper objects from the standard library. I won’t go into the details — you can search online for the words used in the the next code block. When you see it in other people’s work you will be better prepared to understand it from having seen it in this rewrite of our main function:

#include <memory>  //for 'unique_ptr'

int main() {
   _setmode(_fileno(stdout), _O_U16TEXT);

      vector<unique_ptr<Human>> people;

      people.push_back(make_unique<AmericanPerson>(L"Joe"));
   people.push_back(make_unique<ChinesePerson>(L"Li"));
   people.push_back(make_unique<MexicanPerson>(L"Jose"));
   people.push_back(make_unique<GhettoSlanger>(L"Mark"));
   people.push_back(make_unique<JapanesePerson>(L"Hana"));

      for (int speaker=0, numPeople=people.size(); speaker<numPeople; ++speaker) {
      for (int listener=0; listener<numPeople; ++listener) {
         if (speaker != listener) {
            people[speaker]->talkTo(*people[listener]);
            }
         }
      wcout << endl;
      }
   
   wcout << "Press 'Enter' to exit";
   cin.ignore();

         
   return 0;
   }

Download HumanInteractions9.zip — 9KB

And that is everything I wish to share in this article, since my fingers are tired, and it’s time to do something else. This writing has summarized many years of work and learning, and hopefully helps some of you grasp the concepts a little more easily than I did. I know I never covered header files, and a couple other items I brought up, but I will leave that for another edition/iteration, if it is called for. The previous concepts are far more important than the items I’ve left out.

Thanks for reading, and Happy Coding!

History

  • November 24, 2014:
    • In HumanInteractions9, everything I’d read gave me the impression that the unique_ptrs would keep track of type, so the correct destructors would be called without a virtual destructor. But intuition kicked in (of course, after the article was already public : rolleyes : ), so I tested. My conclusion was incorrect (the sources I read were probably correct — I just misread them). Therefore I added a virtual destructor back to the Human class. I apologize for misleading earlier readers of this article, and hope my misstatement is made known to them so they don’t create leaky code as a result of the earlier versions.
    • Corrected a comment about memory locations in HumanInteractions2.
    • Broke up a heavy paragraph, and other minor edits.
    • Changed recommendation from Visual Studio Express to Visual Studio Community Edition, which was made available after the first edition of this article was made public. Of course, if you want a smaller install that doesn’t take up as much disk space, the Express Edition would be the way to go, but the Community Edition gives you more options that are worth the added space in my opinion.
    • Improved const correctness in all the code, in order to set a better example.
  • November 4, 2014: Added virtual destructor to what is now HumanInteractions8 example, which I overlooked in earlier version. (HumanInteractions9 was previously HumanInteractions8.)
  • Remove From My Forums
  • Question

  • Hello,

    I learhing C# and had an issue with understanding class level scope.  I understand it in VB where you post something under class everything can see it however I have tried this in C# and I cannot get it to work.

    Here is the jpeg

    http://i42.tinypic.com/f43cxy.jpg

    I will post the code also:

    using System;
    
    namespace ConsoleApplication6
    {
        class Program
        {
            public int numValue1 = 5;
            public int numValue2 = 10;
    
          
    
            static void Main()
            {
                if(numValue1 < numValue2)
                    Console.WriteLine(" {0} is less than {1} .", numValue1, numValue2);
            }
        }
    }
    

    I have tried moving it around taking out the public, adding in the public…. but I just cannot seem to get it to work…

Answers

  • This has less to do with class level or method level and more to do with whether the values at the class level are instance or static. 

    Variables at the class level are instance if not specified as static, and instance variables cannot be accessed in a static context, such as the Main method.  Try adding «static» to the declaration, ie:

    public static int numValue2 = 10;


    David Morton — http://blog.davemorton.net/ — @davidmmorton — ForumsBrowser, a WPF MSDN Forums Client

    • Marked as answer by

      Friday, July 3, 2009 5:43 PM

Понравилась статья? Поделить с друзьями:
  • Using good word choice
  • Using functions in excel vba
  • Using formula in word
  • Using form fields in word
  • Using form controls in word